Skip to content
You have no unread notifications

Account menu

Jsontran5 Jason Tran
eggert  /   tz  /  
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: eggert/tz
base: 2022f
Choose a base ref
...
head repository: eggert/tz
compare: 2022g
Choose a head ref

Commits on Oct 28, 2022

  1. * NEWS: Credit gera.

    eggert committed Oct 28, 2022
    Copy the full SHA
    e5a7161 View commit details
  2. Copy the full SHA
    5600d65 View commit details
  3. Fix tzalloc bug on platforms lacking tm_zone

    Problem reported by Đoàn Trần Công Danh in:
    https://mm.icann.org/pipermail/tz/2022-October/032153.html
    * NEWS: Mention this.
    * zdump.c (tzalloc) [!USE_LOCALTIME_RZ && HAVE_SETENV]:
    Return a nonnull pointer.
    eggert committed Oct 28, 2022
    Copy the full SHA
    a91830b View commit details
  4. Port struct tm guessing to musl

    Prompted by report from Đoàn Trần Công Danh in:
    https://mm.icann.org/pipermail/tz/2022-October/032153.html
    * private.h (TM_GMTOFF, TM_ZONE): By default, assume they
    work on musl, which #defines __tm_zone.
    eggert committed Oct 28, 2022
    Copy the full SHA
    dbe87fe View commit details
  5. Copy the full SHA
    f4c0967 View commit details
  6. Don’t assume nonempty argv

    Don’t dump core if argv[0] is NULL, which is allowed on
    GNU/Linux if the invoker is sufficiently perverse.
    * zdump.c (progname): Now char const *, so that it can be given
    the address of a string constant.
    (tzalloc): Use optarg, not progname, since progname’s type is no
    longer correct.
    * zdump.c, zic.c (main): Initialize progname to non-null.
    eggert committed Oct 28, 2022
    Copy the full SHA
    b037132 View commit details

Commits on Oct 29, 2022

  1. Update Mexico zone table comments

    Problem reported by Chris Walton in:
    https://mm.icann.org/pipermail/tz/2022-October/032157.html
    * zone.tab, zone1970.tab: Don’t mention time zone names in the
    comments for Mexican entries, as they were obsolete for Chihuahua
    and Ojinaga and were not that helpful anyway in a location-based
    selection.  Reorder based on location more than timezone rules.
    eggert committed Oct 29, 2022
    Copy the full SHA
    9f1f40c View commit details
  2. Update Mexico comments some more

    * northamerica: Update comments to match latest law.  Reorder
    entries (no change to actual data) to make the comments clearer.
    * zone.tab, zone1970.tab: Reorder to put special case of
    Bahía de Banderas after the more-general case of America/Mazatlan,
    and mention in comment that the latter covers only most of Nayarit,
    not all of it.
    eggert committed Oct 29, 2022
    Copy the full SHA
    359a7ae View commit details
  3. Fix GET_RANDOM default on macOS

    Problem reported by Gilmore Davidson in:
    https://mm.icann.org/pipermail/tz/2022-October/032168.html
    * Makefile, NEWS: Mention this and clarify doc.
    * private.h (HAVE_GETRANDOM): Move to ...
    * zic.c: ... here since it’s needed only in zic.c.  Don’t default
    to true on platforms like macOS that have sys/random.h but not
    GRND_RANDOM.
    eggert committed Oct 29, 2022
    Copy the full SHA
    5db8b3b View commit details
  4. Copy the full SHA
    0e1616e View commit details
  5. Make it easier to skip backcheck

    Inspired by a suggestion from Stephen Colebourne in:
    https://mm.icann.org/pipermail/tz/2022-October/032170.html
    * Makefile (check_back, check_mild): New rules, split out
    from existing ones, so that one can use ‘make check_mild’
    instead of ‘make check’ to skip the backcheck.
    * NEWS: Mention this.
    eggert committed Oct 29, 2022
    Copy the full SHA
    2a18b74 View commit details
  6. Pacify compilers re #undef HAVE_GETRANDOM

    * zic.c (HAVE_GETRANDOM): Do not rely on this macro evaluating to
    zero if undefined in an #if.  Although the C standard guarantees
    this, some compilers warn about it.
    eggert committed Oct 29, 2022
    Copy the full SHA
    8411832 View commit details

Commits on Oct 30, 2022

  1. Require explicit -DHAVE_GETTEXT on macOS

    Problem reported by Gilmore Davidson in:
    https://mm.icann.org/pipermail/tz/2022-October/032168.html
    * private.h (HAVE_GETTEXT): On macOS, require an explicit
    -DHAVE_GETTEXT to use gettext.
    eggert committed Oct 30, 2022
    Copy the full SHA
    71958dd View commit details

Commits on Oct 31, 2022

  1. Port better to old Linux kernels

    Problem reported by Igor Ivanov in:
    https://mm.icann.org/pipermail/tz/2022-October/032192.html
    * NEWS: Mention this.
    * zic.c (get_rand_u64): Don’t use clock_gettime; it’s too much of
    a configuration hassle.
    eggert committed Oct 31, 2022
    Copy the full SHA
    317cc2c View commit details
  2. Revert change re default HAVE_GETTEXT on macOS

    * Makefile: Add commentary about this.
    * private.h (HAVE_GETTEXT): Revert previous change in this area.
    eggert committed Oct 31, 2022
    Copy the full SHA
    377e311 View commit details

Commits on Nov 1, 2022

  1. Work around MS-Windows nmake bug

    Work around an nmake incompatibility with POSIX.
    Problem reported by Manuela Friedrich in:
    https://mm.icann.org/pipermail/tz/2022-October/032126.html
    * Makefile (check_sorted): Don’t use ‘^$$/’, which causes
    MS-Windows nmake to report a syntax error and exit due to its
    nonstandard treatment of ‘^$’ to mean ‘$$’, which means the
    following ‘$/’ is a syntax error.  Don’t bother to replace other
    instances of ‘^$’; they are harmless unless you run ‘make check’
    which wouldn’t work on native MS-Windows anyway.
    eggert committed Nov 1, 2022
    Copy the full SHA
    ee3ddc6 View commit details
  2. Copy the full SHA
    b4253bb View commit details

Commits on Nov 4, 2022

  1. Port to AIX 6.1 malloc

    Allocate at least one slot even if unused, so malloc(0)
    is never called, as it can return NULL even on success in AIX.
    Problem reported by Tim McBrayer in:
    https://mm.icann.org/pipermail/tz/2022-November/032210.html
    This bug was introduced the Qt bug 53071 workaround was removed,
    as the workaround allocated one more slot than needed.
    * zic.c (writezone): Don’t malloc(0).
    eggert committed Nov 4, 2022
    Copy the full SHA
    f104933 View commit details
  2. Rename ecpyalloc to estrdup

    Suggested by Guy Harris in:
    https://mm.icann.org/pipermail/tz/2022-November/032213.html
    * zic.c (estrdup): Rename form ecpyalloc.  All uses changed.
    The old name dates back to 1986, before strdup was standardized.
    eggert committed Nov 4, 2022
    Copy the full SHA
    4a69a06 View commit details
  3. Fix unlikely conversion bug in zic

    * zic.c (puttzcode): Arg is zic_t, not int_fast32_t.  This fixes a
    portability bug on platforms where int_fast32_t is a 32-bit ones’
    complement or signed-magnitude integer, and where the argument is
    -2**31 before conversion to int_fast32_t.  Although I don’t know
    of any such platforms, the C standard allows them.
    eggert committed Nov 4, 2022
    Copy the full SHA
    f4808ee View commit details

Commits on Nov 6, 2022

  1. Fix some pre-1996 timestamps in northern Canada

    (Problems reported by Chris Walton.)
    * NEWS: Mention this.
    * backward (America/Pangnirtung): New backward-compatibility link.
    * backzone (America/Pangnirtung): Move here from northamerica,
    except omit the dubious line saying it observed AST.
    * northamerica (NT_YK): Move 1965 transitions ...
    (Yukon): ... to this new Rule.
    (America/Pangnirtung): Move to 'backzone'.
    (America/Whitehorse, America/Dawson): Use new Rule for 1965.
    (America/Whitehorse): Transiton from -09 to -08 was
    1966-02-27, not 1967-05-28.
    * zone.tab, zone1970.tab (America/Pangnirtung): Remove.
    eggert committed Nov 6, 2022
    Copy the full SHA
    45ee615 View commit details
  2. Copy the full SHA
    3609abf View commit details
  3. Copy the full SHA
    9c01173 View commit details
  4. Generate nicer 'make check' output

    * Makefile (DIFF_TZS): New macro.
    (check_tzs, $(TIME_T_ALTERNATIVES)): Use it.
    eggert committed Nov 6, 2022
    Copy the full SHA
    bc4e7f0 View commit details

Commits on Nov 8, 2022

  1. Port mktime and strftime to strict C

    Problem reported by Robert Elz in:
    https://mm.icann.org/pipermail/tz/2022-November/032236.html
    * NEWS: Mention this.
    * localtime.c (time2sub):
    * strftime.c (_fmt): When preparing to call mktime, copy
    only the struct tm components that mktime needs.
    This avoids accessing components that may be uninitialized.
    eggert committed Nov 8, 2022
    Copy the full SHA
    6c713ae View commit details

Commits on Nov 10, 2022

  1. * strftime.c: Improve comment.

    eggert committed Nov 10, 2022
    Copy the full SHA
    40c12e6 View commit details
  2. Support timegm by default, as per C23

    Also, fix a bug in timegm; it sometimes modified its input even on
    failure.
    * Makefile, NEWS: Mention this.
    * localtime.c (mktmcpy): New static function.
    (time2sub): Use it.
    (timegm, timeoff): Define even if !STD_INSPIRED.
    (timeoff): Make it static if !STD_INSPIRED.
    (timegm): Do not modify *TMP on failure, even if only to change
    TMP->is_isdst.
    * private.h (HAVE_DECL_TIMEGM): Specify reasonable default value.
    (timegm): Always declare one way or another.
    eggert committed Nov 10, 2022
    Copy the full SHA
    dd0ed4e View commit details

Commits on Nov 11, 2022

  1. Copy the full SHA
    aaca8fa View commit details

Commits on Nov 12, 2022

  1. Colombia’s 1993 fallback was 02-06 24:00

    (Thanks to Alois Treindl.)
    * NEWS: Mention this.
    * southamerica (CO): Change 1993 fallback to Feb 6 24:00.
    eggert committed Nov 12, 2022
    Copy the full SHA
    bc2942e View commit details

Commits on Nov 18, 2022

  1. Change TF spelling in iso3166.tab

    * iso3166.tab: Change TF spelling from “French Southern & Antarctic
    Lands” to “French Southern Territories" to reflect current ISO 3166.
    I guess the ISO 3166 spelling changed some time between 1996 and now,
    (perhaps to reflect the idea that TF no longer extends into
    Antarctica?) and we never noticed.
    eggert committed Nov 18, 2022
    Copy the full SHA
    1d1aa38 View commit details

Commits on Nov 19, 2022

  1. Improve NEWS "Briefly" summary

    eggert committed Nov 19, 2022
    Copy the full SHA
    f4ca780 View commit details
  2. Port to C89 gcc -pedantic

    * private.h (HAVE_GENERIC, LLONG_MAX, LLONG_MIN):
    Don’t define if compiled with gcc -std=c89 -pedantic,
    since that GCC diagnoses _Generic and long long.
    (ULLONG_MAX): Define if not already defined, and
    if __LONG_LONG_MAX__ and !__STRICT_ANSI__.
    (uint_fast64_t, uintmax_t, PRIuMAX):
    Rely on ULLONG_MAX, not __LONG_LONG_MAX__.
    eggert committed Nov 19, 2022
    Copy the full SHA
    85a4b4a View commit details
  3. Port UINT_FAST64_MAX back to C89

    The recent patch “Improve randomness of zic temp file names”
    used UINT_FAST64_MAX, which assumes C99.
    * private.h (UINT_FAST64_MAX): Define if not already defined.
    Reorganize the fallback a bit, to prefer long to long long
    if either will do.
    eggert committed Nov 19, 2022
    Copy the full SHA
    8b1c6ab View commit details
  4. Port int_fast64_t to C89 64-bit long

    * private.h (int_fast64_t, INT_FAST64_MIN, INT_FAST64_MAX)
    (PRIdFAST64): Prefer long to long long if either will do,
    as that works better on C89 platforms with 64-bit long.
    eggert committed Nov 19, 2022
    Copy the full SHA
    b5a8115 View commit details
  5. * NEWS: Deprecate C89.

    eggert committed Nov 19, 2022
    Copy the full SHA
    43faca9 View commit details
  6. Simplify inputline return value

    * zic.c (inputline): Return bool, not ptrdiff_t.
    All callers changed.
    eggert committed Nov 19, 2022
    Copy the full SHA
    cc82913 View commit details
  7. Minor time2sub refactor

    * localtime.c (time2sub): Refactor to do subtraction
    at compile-time rather than addition at runtime.
    Use yourtm.tm_year instead of y; they’re equal, and
    using yourtm.tm_year simplifies later patches.
    eggert committed Nov 19, 2022
    Copy the full SHA
    1f15b7c View commit details
  8. Refactor zic to simplify overflow checking

    * zic.c (size_product): Return ptrdiff_t not size_t.  The result
    fits in both types, as any sizes greater than PTRDIFF_MAX will
    cause problems elsewhere; and signed types are better in debugging
    implementations that check signed integer overflow.
    (align_to, growalloc): Refactor to simplify
    future transition to ckd_add.
    (grow_nitems_alloc): New static function, to simplify this
    refactoring.
    eggert committed Nov 19, 2022
    Copy the full SHA
    8e303be View commit details
  9. Refactor zic overflow checking

    * zic.c (oadd, tadd): Negate sense of branch,
    to simplify future changes.
    (tadd): Simplify.
    eggert committed Nov 19, 2022
    Copy the full SHA
    ad10807 View commit details
  10. Avoid some size_t values in localtime.c

    * localtime.c (tzloadbody): No need to give a name to strlen(name).
    (tzparse): Prefer ptrdiff_t to size_t where either will do.
    eggert committed Nov 19, 2022
    Copy the full SHA
    c49f087 View commit details
  11. Don’t assume INT_MAX < UINT_FAST64_MAX

    * zic.c (get_rand_u64): Avoid undefined behavior in getrandom
    fallback, on theoretical platforms where UINT_FAST64_MAX <= INT_MAX
    so a * b can have signed integer overflow even though A and B are
    uint_fast64_t.
    eggert committed Nov 19, 2022
    Copy the full SHA
    1d7ab56 View commit details
  12. Fix size_t overflow check if SIZE_MAX == INT_MAX

    * zdump.c (sumsize):
    * zic.c (align_to): Avoid undefined behavior if SIZE_MAX ==
    INT_MAX and adding two sizes overflows.
    eggert committed Nov 19, 2022
    Copy the full SHA
    f55f17a View commit details
  13. date: integer overflow fixes

    * NEWS: Mention this.
    * date.c (dogmt, timeout): Limit allocations to at most
    PTRDIFF_MAX bytes to avoid undefined behavior on pointer subtraction.
    (dogmt): Work even if ‘environ’ has more than INT_MAX entries.
    (timeout): Avoid unnecessary pointer test, as the caller does this.
    Avoid unnecessary copy of struct tm.  Don’t infloop on size_t overflow.
    Double size of array if it’s too small, to avoid O(N**2) CPU.
    * private.h (PTRDIFF_MAX): Move default value here ...
    * zic.c: ... from here, since date.c now uses it.
    eggert committed Nov 19, 2022
    Copy the full SHA
    50a2551 View commit details
  14. Improve integer overflow checking in zdump

    * zdump.c (size_overflow): New function.
    (sumsize): Use it.
    (sumsize, tzalloc): Don’t allow sizes greater than PTRDIFF_MAX,
    as they’re trouble on many platforms.
    (tzalloc, saveabbr, main, hunt, format_local_time)
    (format_utc_offset, format_quoted_string, istrftime, showtrans):
    Prefer ptrdiff_t to size_t where either will do, as we can
    get better runtime overflow checking with signed types.
    (istrftime): Check for size overflow when adding 2 (!).
    eggert committed Nov 19, 2022
    Copy the full SHA
    dcc6bcf View commit details
  15. Fix theoretical integer overflow in zic.c

    * zic.c (FORMAT_LEN_GROWTH_BOUND): New constant.
    (infile): Don’t allocate a local buffer so large that later size
    calculations can overflow.
    (getsave, inzsub, doabbr, stringzone): Prefer ptrdiff_t to
    size_t where either will do, as signed overflow is easier
    for a debugging implementation to check.
    eggert committed Nov 19, 2022
    Copy the full SHA
    2d933ea View commit details
  16. Fix another theoretical zic.c overflow

    * zic.c (size_overflow, size_sum): New functions.
    (size_product, align_to, growalloc, relname):
    Prefer ptrdiff_t to size_t where either will do.
    (random_dirent, relname): Check for unlikely integer overflow.
    eggert committed Nov 19, 2022
    Copy the full SHA
    8288955 View commit details
  17. Prefer <stdckdint.h> for overflow checking

    If <stdckdint.h> is available, or if its macros can be implemented
    easily, use the macros for overflow checking.  This should help avoid
    future integer overflow bugs.
    * date.c (dogmt, timeout):
    * localtime.c (localsub, timesub, increment_overflow)
    (increment_overflow32, increment_overflow_time, time2sub):
    * zdump.c (sumsize, tzalloc):
    * zic.c (size_sum, size_product, grow_nitems_alloc, oadd, tadd):
    Prefer ckd_add etc. to doing overflow checking by hand.
    * private.h (HAVE_STDCKDINT_H): Default to true if
    __has_include(<stdckdint.h>).  Include <stdckdint.h>
    if available.
    (ckd_add, ckd_sub, ckd_mul): Provide substitutes on
    recent-enough GCC-compatible compilers.
    eggert committed Nov 19, 2022
    Copy the full SHA
    57b8fc9 View commit details

Commits on Nov 20, 2022

  1. Use C23 [[maybe_unused]] if available

    * Makefile (GCC_DEBUG_FLAGS): Omit -Wno-unused-parameters, as the
    code is now safe for gcc -Wunused-parameters.
    * private.h (ATTRIBUTE_MAYBE_UNUSED): New macro.
    * localtime.c (gmtsub):
    * strftime.c (strftime_l) [HAVE_STRFTIME_L]:
    * zdump.c (gmtoff):
    Use it to mark possibly-unused parameters.
    * zdump.c (hunt):
    * zic.c (getleapdatetime):
    Omit unused arg. All callers changed.
    eggert committed Nov 20, 2022
    Copy the full SHA
    53b3f12 View commit details

Commits on Nov 21, 2022

  1. Omit unnecessary double-underscores

    This follows up on a comment by Russ Allbery in:
    https://mm.icann.org/pipermail/tz/2022-November/032310.html
    * private.h (ATTRIBUTE_MALLOC, ATTRIBUTE_PURE)
    (ATTRIBUTE_FORMAT, ATTRIBUTE_MAYBE_UNUSED, _Noreturn): Omit double
    underscores around attributes.  They aren’t needed, since
    private.h is not a public include file so we don’t need to worry
    about includers #defining ‘pure’ etc.
    eggert committed Nov 21, 2022
    Copy the full SHA
    15c01af View commit details
  2. Use C23 [[noreturn]] if available

    * private.h (ATTRIBUTE_NORETURN): Rename from _Noreturn, which
    C23 says is obsolescent, and use C23-style [[noreturn]] if available.
    All uses of _Noreturn changed.
    eggert committed Nov 21, 2022
    Copy the full SHA
    dbfcefe View commit details
Showing with 868 additions and 422 deletions.
  1. +34 −21 Makefile
  2. +88 −1 NEWS
  3. +4 −0 africa
  4. +1 −1 asia
  5. +1 −0 backward
  6. +54 −1 backzone
  7. +4 −4 date.1
  8. +22 −22 date.c
  9. +26 −2 europe
  10. +3 −3 iso3166.tab
  11. +74 −20 localtime.c
  12. +3 −3 newctime.3
  13. +2 −2 newstrftime.3
  14. +4 −4 newtzset.3
  15. +92 −69 northamerica
  16. +151 −51 private.h
  17. +7 −2 southamerica
  18. +15 −6 strftime.c
  19. +0 −1 theory.html
  20. +8 −8 time2posix.3
  21. +3 −3 tzfile.5
  22. +3 −3 tzselect.8
  23. +6 −6 zdump.8
  24. +62 −41 zdump.c
  25. +7 −5 zic.8
  26. +168 −117 zic.c
  27. +13 −13 zone.tab
  28. +13 −13 zone1970.tab
55 changes: 34 additions & 21 deletions Makefile
@@ -196,6 +196,7 @@ PACKRATLIST=
UTF8_LOCALE= en_US.utf8 UTF8_LOCALE= en_US.utf8


# Non-default libraries needed to link. # Non-default libraries needed to link.
# On some hosts, this should have -lintl unless CFLAGS has -DHAVE_GETTEXT=0.
LDLIBS= LDLIBS=


# Add the following to the end of the "CFLAGS=" line as needed to override # Add the following to the end of the "CFLAGS=" line as needed to override
@@ -208,14 +209,18 @@ LDLIBS=
# For example, N is 252460800 on AmigaOS. # For example, N is 252460800 on AmigaOS.
# -DHAVE_DECL_ASCTIME_R=0 if <time.h> does not declare asctime_r # -DHAVE_DECL_ASCTIME_R=0 if <time.h> does not declare asctime_r
# -DHAVE_DECL_ENVIRON if <unistd.h> declares 'environ' # -DHAVE_DECL_ENVIRON if <unistd.h> declares 'environ'
# -DHAVE_DECL_TIMEGM=0 if <time.h> does not declare timegm
# -DHAVE_DIRECT_H if mkdir needs <direct.h> (MS-Windows) # -DHAVE_DIRECT_H if mkdir needs <direct.h> (MS-Windows)
# -DHAVE_GENERIC=0 if _Generic does not work # -DHAVE_GENERIC=0 if _Generic does not work*
# -DHAVE_GETRANDOM if getgrandom works (e.g., GNU/Linux)* # -DHAVE_GETRANDOM if getrandom works (e.g., GNU/Linux),
# -DHAVE_GETTEXT if 'gettext' works (e.g., GNU/Linux, FreeBSD, Solaris)* # -DHAVE_GETRANDOM=0 to avoid using getrandom
# -DHAVE_GETTEXT if gettext works (e.g., GNU/Linux, FreeBSD, Solaris),
# where LDLIBS also needs to contain -lintl on some hosts;
# -DHAVE_GETTEXT=0 to avoid using gettext
# -DHAVE_INCOMPATIBLE_CTIME_R if your system's time.h declares # -DHAVE_INCOMPATIBLE_CTIME_R if your system's time.h declares
# ctime_r and asctime_r incompatibly with the POSIX standard # ctime_r and asctime_r incompatibly with the POSIX standard
# (Solaris when _POSIX_PTHREAD_SEMANTICS is not defined). # (Solaris when _POSIX_PTHREAD_SEMANTICS is not defined).
# -DHAVE_INTTYPES_H if you have a non-C99 compiler with <inttypes.h> # -DHAVE_INTTYPES_H=0 if <inttypes.h> does not work*
# -DHAVE_LINK=0 if your system lacks a link function # -DHAVE_LINK=0 if your system lacks a link function
# -DHAVE_LOCALTIME_R=0 if your system lacks a localtime_r function # -DHAVE_LOCALTIME_R=0 if your system lacks a localtime_r function
# -DHAVE_LOCALTIME_RZ=0 if you do not want zdump to use localtime_rz # -DHAVE_LOCALTIME_RZ=0 if you do not want zdump to use localtime_rz
@@ -225,15 +230,17 @@ LDLIBS=
# functions like 'link' or variables like 'tzname' required by POSIX # functions like 'link' or variables like 'tzname' required by POSIX
# -DHAVE_SETENV=0 if your system lacks the setenv function # -DHAVE_SETENV=0 if your system lacks the setenv function
# -DHAVE_SNPRINTF=0 if your system lacks the snprintf function # -DHAVE_SNPRINTF=0 if your system lacks the snprintf function
# -DHAVE_STDINT_H if you have a non-C99 compiler with <stdint.h>* # -DHAVE_STDCKDINT_H=0 if neither <stdckdint.h> nor substitutes like
# __builtin_add_overflow work*
# -DHAVE_STDINT_H=0 if <stdint.h> does not work*
# -DHAVE_STRFTIME_L if <time.h> declares locale_t and strftime_l # -DHAVE_STRFTIME_L if <time.h> declares locale_t and strftime_l
# -DHAVE_STRDUP=0 if your system lacks the strdup function # -DHAVE_STRDUP=0 if your system lacks the strdup function
# -DHAVE_STRTOLL=0 if your system lacks the strtoll function # -DHAVE_STRTOLL=0 if your system lacks the strtoll function
# -DHAVE_SYMLINK=0 if your system lacks the symlink function # -DHAVE_SYMLINK=0 if your system lacks the symlink function
# -DHAVE_SYS_STAT_H=0 if your compiler lacks a <sys/stat.h>* # -DHAVE_SYS_STAT_H=0 if <sys/stat.h> does not work*
# -DHAVE_TZSET=0 if your system lacks a tzset function # -DHAVE_TZSET=0 if your system lacks a tzset function
# -DHAVE_UNISTD_H=0 if your compiler lacks a <unistd.h>* # -DHAVE_UNISTD_H=0 if <unistd.h> does not work*
# -DHAVE_UTMPX_H=0 if your compiler lacks a <utmpx.h>* # -DHAVE_UTMPX_H=0 if <utmpx.h> does not work*
# -Dlocale_t=XXX if your system uses XXX instead of locale_t # -Dlocale_t=XXX if your system uses XXX instead of locale_t
# -DRESERVE_STD_EXT_IDS if your platform reserves standard identifiers # -DRESERVE_STD_EXT_IDS if your platform reserves standard identifiers
# with external linkage, e.g., applications cannot define 'localtime'. # with external linkage, e.g., applications cannot define 'localtime'.
@@ -280,7 +287,7 @@ GCC_DEBUG_FLAGS = -DGCC_LINT -g3 -O3 -fno-common \
-Wdeclaration-after-statement -Wdouble-promotion \ -Wdeclaration-after-statement -Wdouble-promotion \
-Wduplicated-branches -Wduplicated-cond \ -Wduplicated-branches -Wduplicated-cond \
-Wformat=2 -Wformat-overflow=2 -Wformat-signedness -Wformat-truncation \ -Wformat=2 -Wformat-overflow=2 -Wformat-signedness -Wformat-truncation \
-Winit-self -Wlogical-op \ -Wimplicit-fallthrough=5 -Winit-self -Wlogical-op \
-Wmissing-declarations -Wmissing-prototypes -Wnested-externs \ -Wmissing-declarations -Wmissing-prototypes -Wnested-externs \
-Wnull-dereference \ -Wnull-dereference \
-Wold-style-definition -Woverlength-strings -Wpointer-arith \ -Wold-style-definition -Woverlength-strings -Wpointer-arith \
@@ -293,7 +300,7 @@ GCC_DEBUG_FLAGS = -DGCC_LINT -g3 -O3 -fno-common \
-Wtrampolines -Wundef -Wuninitialized -Wunused-macros -Wuse-after-free=3 \ -Wtrampolines -Wundef -Wuninitialized -Wunused-macros -Wuse-after-free=3 \
-Wvariadic-macros -Wvla -Wwrite-strings \ -Wvariadic-macros -Wvla -Wwrite-strings \
-Wno-address -Wno-format-nonliteral -Wno-sign-compare \ -Wno-address -Wno-format-nonliteral -Wno-sign-compare \
-Wno-type-limits -Wno-unused-parameter -Wno-type-limits
# #
# If your system has a "GMT offset" field in its "struct tm"s # If your system has a "GMT offset" field in its "struct tm"s
# (or if you decide to add such a field in your system's "time.h" file), # (or if you decide to add such a field in your system's "time.h" file),
@@ -340,14 +347,11 @@ GCC_DEBUG_FLAGS = -DGCC_LINT -g3 -O3 -fno-common \
# If you want functions that were inspired by early versions of X3J11's work, # If you want functions that were inspired by early versions of X3J11's work,
# add # add
# -DSTD_INSPIRED # -DSTD_INSPIRED
# to the end of the "CFLAGS=" line. This arranges for the functions # to the end of the "CFLAGS=" line. This arranges for the following
# "offtime", "timelocal", "timegm", "timeoff", # functions to be added to the time conversion library.
# "posix2time", and "time2posix" to be added to the time conversion library.
# "offtime" is like "gmtime" except that it accepts a second (long) argument # "offtime" is like "gmtime" except that it accepts a second (long) argument
# that gives an offset to add to the time_t when converting it. # that gives an offset to add to the time_t when converting it.
# "timelocal" is equivalent to "mktime". # "timelocal" is equivalent to "mktime".
# "timegm" is like "timelocal" except that it turns a struct tm into
# a time_t using UT (rather than local time as "timelocal" does).
# "timeoff" is like "timegm" except that it accepts a second (long) argument # "timeoff" is like "timegm" except that it accepts a second (long) argument
# that gives an offset to use when converting to a time_t. # that gives an offset to use when converting to a time_t.
# "posix2time" and "time2posix" are described in an included manual page. # "posix2time" and "time2posix" are described in an included manual page.
@@ -495,6 +499,11 @@ TARFLAGS= `if tar $(GNUTARFLAGS) --version >/dev/null 2>&1; \
# Flags to give 'gzip' when making a distribution. # Flags to give 'gzip' when making a distribution.
GZIPFLAGS= -9n GZIPFLAGS= -9n
# When comparing .tzs files, use GNU diff's -F'^TZ=' option if supported.
# This makes it easier to see which Zone has been affected.
DIFF_TZS= diff -u$$(! diff -u -F'^TZ=' - - <>/dev/null >&0 2>&1 \
|| echo ' -F^TZ=')
############################################################################### ###############################################################################
#MAKE= make #MAKE= make
@@ -773,7 +782,8 @@ tzselect: tzselect.ksh version
chmod +x $@.out chmod +x $@.out
mv $@.out $@ mv $@.out $@
check: check_character_set check_white_space check_links \ check: check_back check_mild
check_mild: check_character_set check_white_space check_links \
check_name_lengths check_slashed_abbrs check_sorted \ check_name_lengths check_slashed_abbrs check_sorted \
check_tables check_web check_ziguard check_zishrink check_tzs check_tables check_web check_ziguard check_zishrink check_tzs
@@ -824,16 +834,19 @@ check_slashed_abbrs: $(TDATA_TO_CHECK)
CHECK_CC_LIST = { n = split($$1,a,/,/); for (i=2; i<=n; i++) print a[1], a[i]; } CHECK_CC_LIST = { n = split($$1,a,/,/); for (i=2; i<=n; i++) print a[1], a[i]; }
check_sorted: backward backzone iso3166.tab zone.tab zone1970.tab check_sorted: backward backzone iso3166.tab zone.tab zone1970.tab
$(AWK) '/^Link/ {printf "%.5d %s\n", g, $$3} /^$$/ {g++}' \ $(AWK) '/^Link/ {printf "%.5d %s\n", g, $$3} !/./ {g++}' \
backward | LC_ALL=C sort -cu backward | LC_ALL=C sort -cu
$(AWK) '/^Zone/ {print $$2}' backzone | LC_ALL=C sort -cu $(AWK) '/^Zone/ {print $$2}' backzone | LC_ALL=C sort -cu
touch $@ touch $@
check_links: checklinks.awk $(TDATA_TO_CHECK) tzdata.zi check_back: checklinks.awk $(TDATA_TO_CHECK)
$(AWK) \ $(AWK) \
-v DATAFORM=$(DATAFORM) \ -v DATAFORM=$(DATAFORM) \
-v backcheck=backward \ -v backcheck=backward \
-f checklinks.awk $(TDATA_TO_CHECK) -f checklinks.awk $(TDATA_TO_CHECK)
touch $@
check_links: checklinks.awk tzdata.zi
$(AWK) \ $(AWK) \
-v DATAFORM=$(DATAFORM) \ -v DATAFORM=$(DATAFORM) \
-f checklinks.awk tzdata.zi -f checklinks.awk tzdata.zi
@@ -849,7 +862,7 @@ check_tables: checktab.awk $(YDATA) backward $(ZONETABLES)
check_tzs: $(TZS) $(TZS_NEW) check_tzs: $(TZS) $(TZS_NEW)
if test -s $(TZS); then \ if test -s $(TZS); then \
diff -u $(TZS) $(TZS_NEW); \ $(DIFF_TZS) $(TZS) $(TZS_NEW); \
else \ else \
cp $(TZS_NEW) $(TZS); \ cp $(TZS_NEW) $(TZS); \
fi fi
@@ -1050,7 +1063,7 @@ $(TIME_T_ALTERNATIVES): $(VERSION_DEPS)
TZS_YEAR="$$range" TZS_CUTOFF_FLAG="-t $$range" \ TZS_YEAR="$$range" TZS_CUTOFF_FLAG="-t $$range" \
D=$$wd/$@.dir \ D=$$wd/$@.dir \
to$$range.tzs) && \ to$$range.tzs) && \
diff -u $(TIME_T_ALTERNATIVES_HEAD).dir/to$$range.tzs \ $(DIFF_TZS) $(TIME_T_ALTERNATIVES_HEAD).dir/to$$range.tzs \
$@.dir/to$$range.tzs && \ $@.dir/to$$range.tzs && \
if diff -q Makefile Makefile 2>/dev/null; then \ if diff -q Makefile Makefile 2>/dev/null; then \
quiet_option='-q'; \ quiet_option='-q'; \
@@ -1220,7 +1233,7 @@ zdump.o: version.h
zic.o: private.h tzfile.h version.h zic.o: private.h tzfile.h version.h
.PHONY: ALL INSTALL all .PHONY: ALL INSTALL all
.PHONY: check check_time_t_alternatives .PHONY: check check_mild check_time_t_alternatives
.PHONY: check_web check_zishrink .PHONY: check_web check_zishrink
.PHONY: clean clean_misc dummy.zd force_tzs .PHONY: clean clean_misc dummy.zd force_tzs
.PHONY: install install_data maintainer-clean names .PHONY: install install_data maintainer-clean names
89 changes: 88 additions & 1 deletion NEWS
@@ -1,5 +1,91 @@
News for the tz database News for the tz database


Release 2022g - 2022-11-29 08:58:31 -0800

Briefly:
The northern edge of Chihuahua changes to US timekeeping.
Much of Greenland stops changing clocks after March 2023.
Fix some pre-1996 timestamps in northern Canada.
C89 is now deprecated; please use C99 or later.
Portability fixes for AIX, libintl, MS-Windows, musl, z/OS
In C code, use more C23 features if available.
C23 timegm now supported by default
Fixes for unlikely integer overflows

Changes to future timestamps

In the Mexican state of Chihuahua, the border strip near the US
will change to agree with nearby US locations on 2022-11-30.
The strip's western part, represented by Ciudad Juárez, switches
from -06 all year to -07/-06 with US DST rules, like El Paso, TX.
The eastern part, represented by Ojinaga, will observe US DST next
year, like Presidio, TX. (Thanks to Heitor David Pinto.)
A new Zone America/Ciudad_Juarez splits from America/Ojinaga.

Much of Greenland, represented by America/Nuuk, stops observing
winter time after March 2023, so its daylight saving time becomes
standard time. (Thanks to Jonas Nyrup and Jürgen Appel.)

Changes to past timestamps

Changes for pre-1996 northern Canada (thanks to Chris Walton):

Merge America/Iqaluit and America/Pangnirtung into the former,
with a backward compatibility link for the latter name.
There is no good evidence the two locations differ since 1970.
This change affects pre-1996 America/Pangnirtung timestamps.

Cambridge Bay, Inuvik, Iqaluit, Rankin Inlet, Resolute and
Yellowknife did not observe DST in 1965, and did observe DST
from 1972 through 1979.

Whitehorse moved from -09 to -08 on 1966-02-27, not 1967-05-28.

Colombia's 1993 fallback was 02-06 24:00, not 04-04 00:00.
(Thanks to Alois Treindl.)

Singapore's 1981-12-31 change was at 16:00 UTC (23:30 local time),
not 24:00 local time. (Thanks to Geoff Clare via Robert Elz.)

Changes to code

Although tzcode still works with C89, bugs found in recent routine
maintenance indicate that bitrot has set in and that in practice
C89 is no longer used to build tzcode. As it is a maintenance
burden, support for C89 is planned to be removed soon. Instead,
please use compilers compatible with C99, C11, C17, or C23.

timegm, which tzcode implemented in 1989, will finally be
standardized 34 years later as part of C23, so timegm is now
supported even if STD_INSPIRED is not defined.

Fix bug in zdump's tzalloc emulation on hosts that lack tm_zone.
(Problem reported by Đoàn Trần Công Danh.)

Fix bug in zic on hosts where malloc(0) yields NULL on success.
(Problem reported by Tim McBrayer for AIX 6.1.)

Fix zic configuration to avoid linkage failures on some platforms.
(Problems reported by Gilmore Davidson and Igor Ivanov.)

Work around MS-Windows nmake incompatibility with POSIX.
(Problem reported by Manuela Friedrich.)

Port mktime and strftime to debugging platforms where accessing
uninitialized data has undefined behavior (strftime problem
reported by Robert Elz).

Check more carefully for unlikely integer overflows, preferring
C23 <stdckdint.h> to overflow checking by hand, as the latter has
had obscure bugs.

Changes to build procedure

New Makefile rule check_mild that skips checking whether Link
lines are in the file 'backward'. (Inspired by a suggestion from
Stephen Colebourne.)


Release 2022f - 2022-10-28 18:04:57 -0700 Release 2022f - 2022-10-28 18:04:57 -0700


Briefly: Briefly:
@@ -16,14 +102,15 @@ Release 2022f - 2022-10-28 18:04:57 -0700
In C code, use some C23 features if available. In C code, use some C23 features if available.
Remove no-longer-needed workaround for Qt bug 53071. Remove no-longer-needed workaround for Qt bug 53071.


Changes to future timestamps. Changes to future timestamps


Mexico will no longer observe DST after 2022, except for areas Mexico will no longer observe DST after 2022, except for areas
near the US border that continue to observe US DST rules. near the US border that continue to observe US DST rules.
On 2022-10-30 at 02:00 the Mexican state of Chihuahua moves On 2022-10-30 at 02:00 the Mexican state of Chihuahua moves
from -07 (-06 with DST) to year-round -06, thus not changing from -07 (-06 with DST) to year-round -06, thus not changing
its clocks that day. The new law states that Chihuahua its clocks that day. The new law states that Chihuahua
near the US border no longer observes US DST. near the US border no longer observes US DST.
(Thanks to gera for the heads-up about Chihuahua.)


Fiji will not observe DST in 2022/3. (Thanks to Shalvin Narayan.) Fiji will not observe DST in 2022/3. (Thanks to Shalvin Narayan.)
For now, assume DST is suspended indefinitely. For now, assume DST is suspended indefinitely.
4 changes: 4 additions & 0 deletions africa
@@ -588,6 +588,10 @@ Zone Indian/Mauritius 3:50:00 - LMT 1907 # Port Louis
# Agalega Is, Rodriguez # Agalega Is, Rodriguez
# no information; probably like Indian/Mauritius # no information; probably like Indian/Mauritius



# Morocco
# See Africa/Ceuta for Spanish Morocco.

# From Alex Krivenyshev (2008-05-09): # From Alex Krivenyshev (2008-05-09):
# Here is an article that Morocco plan to introduce Daylight Saving Time between # Here is an article that Morocco plan to introduce Daylight Saving Time between
# 1 June, 2008 and 27 September, 2008. # 1 June, 2008 and 27 September, 2008.
2 changes: 1 addition & 1 deletion asia
@@ -3585,7 +3585,7 @@ Zone Asia/Singapore 6:55:25 - LMT 1901 Jan 1
7:20 - +0720 1941 Sep 1 7:20 - +0720 1941 Sep 1
7:30 - +0730 1942 Feb 16 7:30 - +0730 1942 Feb 16
9:00 - +09 1945 Sep 12 9:00 - +09 1945 Sep 12
7:30 - +0730 1982 Jan 1 7:30 - +0730 1981 Dec 31 16:00u
8:00 - +08 8:00 - +08


# Spratly Is # Spratly Is
1 change: 1 addition & 0 deletions backward
@@ -267,6 +267,7 @@ Link America/Tijuana America/Ensenada
Link America/Indiana/Indianapolis America/Fort_Wayne Link America/Indiana/Indianapolis America/Fort_Wayne
Link America/Toronto America/Montreal Link America/Toronto America/Montreal
Link America/Toronto America/Nipigon Link America/Toronto America/Nipigon
Link America/Iqaluit America/Pangnirtung
Link America/Rio_Branco America/Porto_Acre Link America/Rio_Branco America/Porto_Acre
Link America/Winnipeg America/Rainy_River Link America/Winnipeg America/Rainy_River
Link America/Argentina/Cordoba America/Rosario Link America/Argentina/Cordoba America/Rosario
55 changes: 54 additions & 1 deletion backzone
@@ -7,6 +7,10 @@
# tz@iana.org for general use in the future). For more, please see # tz@iana.org for general use in the future). For more, please see
# the file CONTRIBUTING in the tz distribution. # the file CONTRIBUTING in the tz distribution.


# When proposing changes to this file, please use 'git format-patch'
# format, either by attaching the resulting .patch file to your email,
# or by using 'git send-email'. This will help maintainers save time.



# From Paul Eggert (2014-10-31): # From Paul Eggert (2014-10-31):


@@ -750,6 +754,55 @@ Zone America/Nipigon -5:53:04 - LMT 1895
-5:00 1:00 EDT 1942 Feb 9 2:00s -5:00 1:00 EDT 1942 Feb 9 2:00s
-5:00 Canada E%sT -5:00 Canada E%sT


# From Rives McDow (1999-11-08):
# On October 31, when the rest of Nunavut went to Central time,
# Pangnirtung wobbled. Here is the result of their wobble:
#
# The following businesses and organizations in Pangnirtung use Central Time:
#
# First Air, Power Corp, Nunavut Construction, Health Center, RCMP,
# Eastern Arctic National Parks, A & D Specialist
#
# The following businesses and organizations in Pangnirtung use Eastern Time:
#
# Hamlet office, All other businesses, Both schools, Airport operator
#
# This has made for an interesting situation there, which warranted the news.
# No one there that I spoke with seems concerned, or has plans to
# change the local methods of keeping time, as it evidently does not
# really interfere with any activities or make things difficult locally.
# They plan to celebrate New Year's turn-over twice, one hour apart,
# so it appears that the situation will last at least that long.
# The Nunavut Intergovernmental Affairs hopes that they will "come to
# their senses", but the locals evidently don't see any problem with
# the current state of affairs.

# From Michaela Rodrigue, writing in the
# Nunatsiaq News (1999-11-19):
# http://www.nunatsiaqonline.ca/archives/nunavut991130/nvt91119_17.html
# Clyde River, Pangnirtung and Sanikiluaq now operate with two time zones,
# central - or Nunavut time - for government offices, and eastern time
# for municipal offices and schools.... Igloolik [was similar but then]
# made the switch to central time on Saturday, Nov. 6.

# From Chris Walton (2022-11-06):
# The implication is that Pangnirtung and Qikiqtarjuaq have observed Eastern
# Time as far back as 1984 (and likely even further back than that).
# It is possible that these communities never actually observed Atlantic
# Time, but that would be difficult to prove.
# From Paul Eggert (2022-11-06):
# This is in 'backzone' as we have no good evidence that Pangnirtung differs
# from America/Iqaluit since 1970. A Google Books snippet view of
# volume 2, page 186 of "Pilot of Arctic Canada", published 1959 by
# the Canadian Hydrographic Service, suggests (though does not state)
# that Pangnirtung observed EST then.
#
# aka Panniqtuuq
Zone America/Pangnirtung 0 - -00 1921 # trading post est.
-5:00 NT_YK E%sT 1999 Oct 31 2:00
-6:00 Canada C%sT 2000 Oct 29 2:00
-5:00 Canada E%sT

# United States # United States
# #
# From Paul Eggert (2018-03-18): # From Paul Eggert (2018-03-18):
@@ -1043,7 +1096,7 @@ Zone Asia/Kuala_Lumpur 6:46:46 - LMT 1901 Jan 1
7:20 - +0720 1941 Sep 1 7:20 - +0720 1941 Sep 1
7:30 - +0730 1942 Feb 16 7:30 - +0730 1942 Feb 16
9:00 - +09 1945 Sep 12 9:00 - +09 1945 Sep 12
7:30 - +0730 1982 Jan 1 7:30 - +0730 1981 Dec 31 16:00u
8:00 - +08 8:00 - +08


# Kuwait # Kuwait
8 changes: 4 additions & 4 deletions date.1
@@ -1,10 +1,12 @@
.TH DATE 1 .\" This file is in the public domain, so clarified as of
.\" 2009-05-17 by Arthur David Olson.
.TH date 1
.SH NAME .SH NAME
date \- show and set date and time date \- show and set date and time
.SH SYNOPSIS .SH SYNOPSIS
.if n .nh .if n .nh
.if n .na .if n .na
.ie \n(.g .ds - \f(CW-\fP .ie \n(.g .ds - \f(CR-\fP
.el .ds - \- .el .ds - \-
.B date .B date
[ [
@@ -163,5 +165,3 @@ If
is absent, is absent,
UTC leap seconds are loaded from UTC leap seconds are loaded from
.BR /usr/share/zoneinfo/posixrules . .BR /usr/share/zoneinfo/posixrules .
.\" This file is in the public domain, so clarified as of
.\" 2009-05-17 by Arthur David Olson.
44 changes: 22 additions & 22 deletions date.c
@@ -42,7 +42,7 @@ static void display(const char *, time_t);
static void dogmt(void); static void dogmt(void);
static void errensure(void); static void errensure(void);
static void timeout(FILE *, const char *, const struct tm *); static void timeout(FILE *, const char *, const struct tm *);
static _Noreturn void usage(void); static ATTRIBUTE_NORETURN void usage(void);


int int
main(const int argc, char *argv[]) main(const int argc, char *argv[])
@@ -117,14 +117,19 @@ dogmt(void)
static char ** fakeenv; static char ** fakeenv;


if (fakeenv == NULL) { if (fakeenv == NULL) {
register int from;
register int to;
register int n;
static char tzeutc0[] = "TZ=UTC0"; static char tzeutc0[] = "TZ=UTC0";
ptrdiff_t from, to, n;


for (n = 0; environ[n] != NULL; ++n) for (n = 0; environ[n] != NULL; ++n)
continue; continue;
fakeenv = malloc((n + 2) * sizeof *fakeenv); #if defined ckd_add && defined ckd_mul
if (!ckd_add(&n, n, 2) && !ckd_mul(&n, n, sizeof *fakeenv)
&& n <= SIZE_MAX)
fakeenv = malloc(n);
#else
if (n <= min(PTRDIFF_MAX, SIZE_MAX) / sizeof *fakeenv - 2)
fakeenv = malloc((n + 2) * sizeof *fakeenv);
#endif
if (fakeenv == NULL) { if (fakeenv == NULL) {
fprintf(stderr, _("date: Memory exhausted\n")); fprintf(stderr, _("date: Memory exhausted\n"));
errensure(); errensure();
@@ -183,33 +188,28 @@ display(char const *format, time_t now)
static void static void
timeout(FILE *fp, char const *format, struct tm const *tmp) timeout(FILE *fp, char const *format, struct tm const *tmp)
{ {
char * cp; char *cp = NULL;
size_t result; ptrdiff_t result;
size_t size; ptrdiff_t size = 1024 / 2;
struct tm tm;
int INCR = 1024;


if (!tmp) {
fprintf(stderr, _("date: error: time out of range\n"));
errensure();
return;
}
tm = *tmp;
tmp = &tm;
size = INCR;
cp = malloc(size);
for ( ; ; ) { for ( ; ; ) {
if (cp == NULL) { #ifdef ckd_mul
bool bigger = !ckd_mul(&size, size, 2) && size <= SIZE_MAX;
#else
bool bigger = (size <= min(PTRDIFF_MAX, SIZE_MAX) / 2
&& (size *= 2, true));
#endif
char *newcp = bigger ? realloc(cp, size) : NULL;
if (!newcp) {
fprintf(stderr, fprintf(stderr,
_("date: error: can't get memory\n")); _("date: error: can't get memory\n"));
errensure(); errensure();
exit(retval); exit(retval);
} }
cp = newcp;
result = strftime(cp, size, format, tmp); result = strftime(cp, size, format, tmp);
if (result != 0) if (result != 0)
break; break;
size += INCR;
cp = realloc(cp, size);
} }
fwrite(cp + 1, 1, result - 1, fp); fwrite(cp + 1, 1, result - 1, fp);
free(cp); free(cp);
28 changes: 26 additions & 2 deletions europe
@@ -1103,7 +1103,30 @@ Zone Atlantic/Faroe -0:27:04 - LMT 1908 Jan 11 # Tórshavn
# "National Park" by Executive Order: # "National Park" by Executive Order:
# http://naalakkersuisut.gl/~/media/Nanoq/Files/Attached%20Files/Engelske-tekster/Legislation/Executive%20Order%20National%20Park.rtf # http://naalakkersuisut.gl/~/media/Nanoq/Files/Attached%20Files/Engelske-tekster/Legislation/Executive%20Order%20National%20Park.rtf
# It is their only National Park. # It is their only National Park.
#
# From Jonas Nyrup (2022-11-24):
# On last Saturday in October 2023 when DST ends America/Nuuk will switch
# from -03/-02 to -02/-01
# https://sermitsiaq.ag/forslagtidsforskel-danmark-mindskes-sommertid-beholdes
# ...
# https://sermitsiaq.ag/groenland-skifte-tidszone-trods-bekymringer
#
# From Jürgen Appel (2022-11-25):
# https://ina.gl/samlinger/oversigt-over-samlinger/samling/dagsordener/dagsorden.aspx?lang=da&day=24-11-2022
# If I understand this correctly, from the next planned switch to
# summer time, Greenland will permanently stay at that time, i.e. no
# switch back to winter time in 2023 will occur.
#
# From Paul Eggert (2022-11-28):
# The official document in Danish
# https://naalakkersuisut.gl/-/media/naalakkersuisut/filer/kundgoerelser/2022/11/2511/31_da_inatsisartutlov-om-tidens-bestemmelse.pdf?la=da&hash=A33597D8A38CC7038465241119EF34F3
# says standard time for Greenland is -02, that Naalakkersuisut can lay down
# rules for DST and can require some areas to use a different time zone,
# and that this all takes effect 2023-03-25 22:00. The abovementioned
# "bekymringer" URL says the intent is no transition March 25, that
# Greenland will not go back to winter time in fall 2023, and that
# only America/Nuuk is affected (though further changes may occur).

# Rule NAME FROM TO - IN ON AT SAVE LETTER/S # Rule NAME FROM TO - IN ON AT SAVE LETTER/S
Rule Thule 1991 1992 - Mar lastSun 2:00 1:00 D Rule Thule 1991 1992 - Mar lastSun 2:00 1:00 D
Rule Thule 1991 1992 - Sep lastSun 2:00 0 S Rule Thule 1991 1992 - Sep lastSun 2:00 0 S
@@ -1126,7 +1149,8 @@ Zone America/Scoresbysund -1:27:52 - LMT 1916 Jul 28 # Ittoqqortoormiit
-1:00 EU -01/+00 -1:00 EU -01/+00
Zone America/Nuuk -3:26:56 - LMT 1916 Jul 28 # Godthåb Zone America/Nuuk -3:26:56 - LMT 1916 Jul 28 # Godthåb
-3:00 - -03 1980 Apr 6 2:00 -3:00 - -03 1980 Apr 6 2:00
-3:00 EU -03/-02 -3:00 EU -03/-02 2023 Mar 25 22:00
-2:00 - -02
Zone America/Thule -4:35:08 - LMT 1916 Jul 28 # Pituffik Zone America/Thule -4:35:08 - LMT 1916 Jul 28 # Pituffik
-4:00 Thule A%sT -4:00 Thule A%sT


6 changes: 3 additions & 3 deletions iso3166.tab
@@ -3,13 +3,13 @@
# This file is in the public domain, so clarified as of # This file is in the public domain, so clarified as of
# 2009-05-17 by Arthur David Olson. # 2009-05-17 by Arthur David Olson.
# #
# From Paul Eggert (2015-05-02): # From Paul Eggert (2022-11-18):
# This file contains a table of two-letter country codes. Columns are # This file contains a table of two-letter country codes. Columns are
# separated by a single tab. Lines beginning with '#' are comments. # separated by a single tab. Lines beginning with '#' are comments.
# All text uses UTF-8 encoding. The columns of the table are as follows: # All text uses UTF-8 encoding. The columns of the table are as follows:
# #
# 1. ISO 3166-1 alpha-2 country code, current as of # 1. ISO 3166-1 alpha-2 country code, current as of
# ISO 3166-1 N976 (2018-11-06). See: Updates on ISO 3166-1 # ISO 3166-1 N1087 (2022-09-02). See: Updates on ISO 3166-1
# https://isotc.iso.org/livelink/livelink/Open/16944257 # https://isotc.iso.org/livelink/livelink/Open/16944257
# 2. The usual English name for the coded region, # 2. The usual English name for the coded region,
# chosen so that alphabetic sorting of subsets produces helpful lists. # chosen so that alphabetic sorting of subsets produces helpful lists.
@@ -238,7 +238,7 @@ SY Syria
SZ Eswatini (Swaziland) SZ Eswatini (Swaziland)
TC Turks & Caicos Is TC Turks & Caicos Is
TD Chad TD Chad
TF French Southern & Antarctic Lands TF French Southern Territories
TG Togo TG Togo
TH Thailand TH Thailand
TJ Tajikistan TJ Tajikistan
94 changes: 74 additions & 20 deletions localtime.c
@@ -425,8 +425,7 @@ tzloadbody(char const *name, struct state *sp, bool doextend,
#endif #endif
if (!doaccess) { if (!doaccess) {
char const *dot; char const *dot;
size_t namelen = strlen(name); if (sizeof lsp->fullname - sizeof tzdirslash <= strlen(name))
if (sizeof lsp->fullname - sizeof tzdirslash <= namelen)
return ENAMETOOLONG; return ENAMETOOLONG;


/* Create a string "TZDIR/NAME". Using sprintf here /* Create a string "TZDIR/NAME". Using sprintf here
@@ -839,7 +838,7 @@ is_digit(char c)
** Return a pointer to that character. ** Return a pointer to that character.
*/ */


static ATTRIBUTE_PURE const char * static ATTRIBUTE_REPRODUCIBLE const char *
getzname(register const char *strp) getzname(register const char *strp)
{ {
register char c; register char c;
@@ -860,7 +859,7 @@ getzname(register const char *strp)
** We don't do any checking here; checking is done later in common-case code. ** We don't do any checking here; checking is done later in common-case code.
*/ */


static ATTRIBUTE_PURE const char * static ATTRIBUTE_REPRODUCIBLE const char *
getqzname(register const char *strp, const int delim) getqzname(register const char *strp, const int delim)
{ {
register int c; register int c;
@@ -1120,13 +1119,11 @@ tzparse(const char *name, struct state *sp, struct state *basep)
{ {
const char * stdname; const char * stdname;
const char * dstname; const char * dstname;
size_t stdlen;
size_t dstlen;
size_t charcnt;
int_fast32_t stdoffset; int_fast32_t stdoffset;
int_fast32_t dstoffset; int_fast32_t dstoffset;
register char * cp; register char * cp;
register bool load_ok; register bool load_ok;
ptrdiff_t stdlen, dstlen, charcnt;
time_t atlo = TIME_T_MIN, leaplo = TIME_T_MIN; time_t atlo = TIME_T_MIN, leaplo = TIME_T_MIN;


stdname = name; stdname = name;
@@ -1568,6 +1565,14 @@ localsub(struct state const *sp, time_t const *timep, int_fast32_t setname,
return NULL; /* "cannot happen" */ return NULL; /* "cannot happen" */
result = localsub(sp, &newt, setname, tmp); result = localsub(sp, &newt, setname, tmp);
if (result) { if (result) {
#if defined ckd_add && defined ckd_sub
if (t < sp->ats[0]
? ckd_sub(&result->tm_year,
result->tm_year, years)
: ckd_add(&result->tm_year,
result->tm_year, years))
return NULL;
#else
register int_fast64_t newy; register int_fast64_t newy;


newy = result->tm_year; newy = result->tm_year;
@@ -1577,6 +1582,7 @@ localsub(struct state const *sp, time_t const *timep, int_fast32_t setname,
if (! (INT_MIN <= newy && newy <= INT_MAX)) if (! (INT_MIN <= newy && newy <= INT_MAX))
return NULL; return NULL;
result->tm_year = newy; result->tm_year = newy;
#endif
} }
return result; return result;
} }
@@ -1656,8 +1662,8 @@ localtime_r(const time_t *timep, struct tm *tmp)
*/ */


static struct tm * static struct tm *
gmtsub(struct state const *sp, time_t const *timep, int_fast32_t offset, gmtsub(ATTRIBUTE_MAYBE_UNUSED struct state const *sp, time_t const *timep,
struct tm *tmp) int_fast32_t offset, struct tm *tmp)
{ {
register struct tm * result; register struct tm * result;


@@ -1786,6 +1792,12 @@ timesub(const time_t *timep, int_fast32_t offset,
y = newy; y = newy;
} }


#ifdef ckd_add
if (ckd_add(&tmp->tm_year, y, -TM_YEAR_BASE)) {
errno = EOVERFLOW;
return NULL;
}
#else
if (!TYPE_SIGNED(time_t) && y < TM_YEAR_BASE) { if (!TYPE_SIGNED(time_t) && y < TM_YEAR_BASE) {
int signed_y = y; int signed_y = y;
tmp->tm_year = signed_y - TM_YEAR_BASE; tmp->tm_year = signed_y - TM_YEAR_BASE;
@@ -1796,6 +1808,7 @@ timesub(const time_t *timep, int_fast32_t offset,
errno = EOVERFLOW; errno = EOVERFLOW;
return NULL; return NULL;
} }
#endif
tmp->tm_yday = idays; tmp->tm_yday = idays;
/* /*
** The "extra" mods below avoid overflow problems. ** The "extra" mods below avoid overflow problems.
@@ -1870,6 +1883,9 @@ ctime_r(const time_t *timep, char *buf)
static bool static bool
increment_overflow(int *ip, int j) increment_overflow(int *ip, int j)
{ {
#ifdef ckd_add
return ckd_add(ip, *ip, j);
#else
register int const i = *ip; register int const i = *ip;


/* /*
@@ -1882,22 +1898,30 @@ increment_overflow(int *ip, int j)
return true; return true;
*ip += j; *ip += j;
return false; return false;
#endif
} }


static bool static bool
increment_overflow32(int_fast32_t *const lp, int const m) increment_overflow32(int_fast32_t *const lp, int const m)
{ {
#ifdef ckd_add
return ckd_add(lp, *lp, m);
#else
register int_fast32_t const l = *lp; register int_fast32_t const l = *lp;


if ((l >= 0) ? (m > INT_FAST32_MAX - l) : (m < INT_FAST32_MIN - l)) if ((l >= 0) ? (m > INT_FAST32_MAX - l) : (m < INT_FAST32_MIN - l))
return true; return true;
*lp += m; *lp += m;
return false; return false;
#endif
} }


static bool static bool
increment_overflow_time(time_t *tp, int_fast32_t j) increment_overflow_time(time_t *tp, int_fast32_t j)
{ {
#ifdef ckd_add
return ckd_add(tp, *tp, j);
#else
/* /*
** This is like ** This is like
** 'if (! (TIME_T_MIN <= *tp + j && *tp + j <= TIME_T_MAX)) ...', ** 'if (! (TIME_T_MIN <= *tp + j && *tp + j <= TIME_T_MAX)) ...',
@@ -1909,6 +1933,7 @@ increment_overflow_time(time_t *tp, int_fast32_t j)
return true; return true;
*tp += j; *tp += j;
return false; return false;
#endif
} }


static bool static bool
@@ -1951,6 +1976,23 @@ tmcomp(register const struct tm *const atmp,
return result; return result;
} }


/* Copy to *DEST from *SRC. Copy only the members needed for mktime,
as other members might not be initialized. */
static void
mktmcpy(struct tm *dest, struct tm const *src)
{
dest->tm_sec = src->tm_sec;
dest->tm_min = src->tm_min;
dest->tm_hour = src->tm_hour;
dest->tm_mday = src->tm_mday;
dest->tm_mon = src->tm_mon;
dest->tm_year = src->tm_year;
dest->tm_isdst = src->tm_isdst;
#if defined TM_GMTOFF && ! UNINIT_TRAP
dest->TM_GMTOFF = src->TM_GMTOFF;
#endif
}

static time_t static time_t
time2sub(struct tm *const tmp, time2sub(struct tm *const tmp,
struct tm *(*funcp)(struct state const *, time_t const *, struct tm *(*funcp)(struct state const *, time_t const *,
@@ -1972,7 +2014,8 @@ time2sub(struct tm *const tmp,
struct tm yourtm, mytm; struct tm yourtm, mytm;


*okayp = false; *okayp = false;
yourtm = *tmp; mktmcpy(&yourtm, tmp);

if (do_norm_secs) { if (do_norm_secs) {
if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec, if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
SECSPERMIN)) SECSPERMIN))
@@ -2014,14 +2057,19 @@ time2sub(struct tm *const tmp,
return WRONG; return WRONG;
} }
} }
#ifdef ckd_add
if (ckd_add(&yourtm.tm_year, y, -TM_YEAR_BASE))
return WRONG;
#else
if (increment_overflow32(&y, -TM_YEAR_BASE)) if (increment_overflow32(&y, -TM_YEAR_BASE))
return WRONG; return WRONG;
if (! (INT_MIN <= y && y <= INT_MAX)) if (! (INT_MIN <= y && y <= INT_MAX))
return WRONG; return WRONG;
yourtm.tm_year = y; yourtm.tm_year = y;
#endif
if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN) if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
saved_seconds = 0; saved_seconds = 0;
else if (y + TM_YEAR_BASE < EPOCH_YEAR) { else if (yourtm.tm_year < EPOCH_YEAR - TM_YEAR_BASE) {
/* /*
** We can't set tm_sec to 0, because that might push the ** We can't set tm_sec to 0, because that might push the
** time below the minimum representable time. ** time below the minimum representable time.
@@ -2278,21 +2326,16 @@ mktime(struct tm *tmp)
} }


#ifdef STD_INSPIRED #ifdef STD_INSPIRED

time_t time_t
timelocal(struct tm *tmp) timelocal(struct tm *tmp)
{ {
if (tmp != NULL) if (tmp != NULL)
tmp->tm_isdst = -1; /* in case it wasn't initialized */ tmp->tm_isdst = -1; /* in case it wasn't initialized */
return mktime(tmp); return mktime(tmp);
} }

#else
time_t static
timegm(struct tm *tmp) #endif
{
return timeoff(tmp, 0);
}

time_t time_t
timeoff(struct tm *tmp, long offset) timeoff(struct tm *tmp, long offset)
{ {
@@ -2302,7 +2345,18 @@ timeoff(struct tm *tmp, long offset)
return time1(tmp, gmtsub, gmtptr, offset); return time1(tmp, gmtsub, gmtptr, offset);
} }


#endif /* defined STD_INSPIRED */ time_t
timegm(struct tm *tmp)
{
time_t t;
struct tm tmcpy;
mktmcpy(&tmcpy, tmp);
tmcpy.tm_wday = -1;
t = timeoff(&tmcpy, 0);
if (0 <= tmcpy.tm_wday)
*tmp = tmcpy;
return t;
}


static int_fast32_t static int_fast32_t
leapcorr(struct state const *sp, time_t t) leapcorr(struct state const *sp, time_t t)
6 changes: 3 additions & 3 deletions newctime.3
@@ -1,9 +1,11 @@
.\" This file is in the public domain, so clarified as of
.\" 2009-05-17 by Arthur David Olson.
.TH NEWCTIME 3 .TH NEWCTIME 3
.SH NAME .SH NAME
asctime, ctime, difftime, gmtime, localtime, mktime \- convert date and time asctime, ctime, difftime, gmtime, localtime, mktime \- convert date and time
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.ie \n(.g .ds - \f(CW-\fP .ie \n(.g .ds - \f(CR-\fP
.el .ds - \- .el .ds - \-
.B #include <time.h> .B #include <time.h>
.PP .PP
@@ -340,5 +342,3 @@ restricted to years in the range 1900 through 2099.
To avoid this portability mess, new programs should use To avoid this portability mess, new programs should use
.B strftime .B strftime
instead. instead.
.\" This file is in the public domain, so clarified as of
.\" 2009-05-17 by Arthur David Olson.
4 changes: 2 additions & 2 deletions newstrftime.3
@@ -40,7 +40,7 @@
strftime \- format date and time strftime \- format date and time
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.ie \n(.g .ds - \f(CW-\fP .ie \n(.g .ds - \f(CR-\fP
.el .ds - \- .el .ds - \-
.B #include <time.h> .B #include <time.h>
.PP .PP
@@ -55,7 +55,7 @@ strftime \- format date and time
.ie '\(rq'' .ds rq \&"\" .ie '\(rq'' .ds rq \&"\"
.el .ds rq \(rq\" .el .ds rq \(rq\"
.de c .de c
.ie \n(.g \f(CW\\$1\fP\\$2 .ie \n(.g \f(CR\\$1\fP\\$2
.el \\$1\\$2 .el \\$1\\$2
.. ..
.de q .de q
8 changes: 4 additions & 4 deletions newtzset.3
@@ -1,9 +1,11 @@
.\" This file is in the public domain, so clarified as of
.\" 2009-05-17 by Arthur David Olson.
.TH NEWTZSET 3 .TH NEWTZSET 3
.SH NAME .SH NAME
tzset \- initialize time conversion information tzset \- initialize time conversion information
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.ie \n(.g .ds - \f(CW-\fP .ie \n(.g .ds - \f(CR-\fP
.el .ds - \- .el .ds - \-
.B #include <time.h> .B #include <time.h>
.PP .PP
@@ -331,7 +333,7 @@ from the rest of the specification.
.br .br
/usr/share/zoneinfo/localtime local timezone file /usr/share/zoneinfo/localtime local timezone file
.br .br
/usr/share/zoneinfo/posixrules used with POSIX-style TZ's /usr/share/zoneinfo/posixrules used with POSIX-style TZ
.br .br
/usr/share/zoneinfo/GMT for UTC leap seconds /usr/share/zoneinfo/GMT for UTC leap seconds
.sp .sp
@@ -346,5 +348,3 @@ newctime(3),
newstrftime(3), newstrftime(3),
time(2), time(2),
tzfile(5) tzfile(5)
.\" This file is in the public domain, so clarified as of
.\" 2009-05-17 by Arthur David Olson.
161 changes: 92 additions & 69 deletions northamerica
@@ -1969,6 +1969,37 @@ Zone America/Fort_Nelson -8:10:47 - LMT 1884


# Northwest Territories, Nunavut, Yukon # Northwest Territories, Nunavut, Yukon


# From Chris Walton (2022-11-06):
# Whitehorse Star - Thursday April 22, 1965 - page 1
# title: DST Starts Monday ...
# https://www.newspapers.com/image/578587481/
# The title of this first article is wrong and/or misleading.
# Also, the start time shown in the article is vague; it simply says "after
# midnight" when it probably should have stated 2:00a.m....
#
# Whitehorse Star - Monday October 25, 1965 - page 15 ...
# https://www.newspapers.com/image/578589147/
# The 1965 Yukon Council minutes can be found here:
# http://assets.yukonarchives.ca/PER_YG_06_1965_C20_S02_v1.pdf
# ... I do not currently believe that NWT touched any of its clocks in 1965....
#
# Whitehorse Star - Thursday Feb 24,1966 - page 2
# title: It's Time for YDT ...
# https://www.newspapers.com/image/578575979/ ...
# America/Whitehorse as a permanent change from UTC-9(YST) to
# UTC-8(PST) at 00:00 on Sunday February 27, 1966....
#
# Whitehorse Star - Friday April 28,1972 - page 6
# title: Daylight Saving Time for N.W.T....
# https://www.newspapers.com/image/578701610/ ...
# Nunavut and NWT zones ... DST starting in 1972.... Start and End ...
# should be the same as the rest of Canada
#
#
# From Paul Eggert (2022-11-06):
# For now, assume Yukon's 1965-04-22 spring forward was 00:00 -> 02:00, as this
# seems likely than 02:00 -> 04:00 and matches "after midnight".

# From Paul Eggert (2006-03-22): # From Paul Eggert (2006-03-22):
# Dawson switched to PST in 1973. Inuvik switched to MST in 1979. # Dawson switched to PST in 1973. Inuvik switched to MST in 1979.
# Mathew Englander (1996-10-07) gives the following refs: # Mathew Englander (1996-10-07) gives the following refs:
@@ -2083,6 +2114,13 @@ Zone America/Fort_Nelson -8:10:47 - LMT 1884
# * Interpretation Act, RSY 2002, c 125 # * Interpretation Act, RSY 2002, c 125
# https://www.canlii.org/en/yk/laws/stat/rsy-2002-c-125/latest/rsy-2002-c-125.html # https://www.canlii.org/en/yk/laws/stat/rsy-2002-c-125/latest/rsy-2002-c-125.html


# From Chris Walton (2022-11-06):
# The 5th edition of the Atlas of Canada contains a time zone map that
# shows both legislated and observed time zone boundaries.
# All communities on Baffin Island are shown to be observing Eastern time.
# The date on the map is 1984.
# https://ftp.maps.canada.ca/pub/nrcan_rncan/raster/atlas_5_ed/eng/other/referencemaps/mcr4056.pdf

# From Rives McDow (1999-09-04): # From Rives McDow (1999-09-04):
# Nunavut ... moved ... to incorporate the whole territory into one time zone. # Nunavut ... moved ... to incorporate the whole territory into one time zone.
# Nunavut moves to single time zone Oct. 31 # Nunavut moves to single time zone Oct. 31
@@ -2095,40 +2133,7 @@ Zone America/Fort_Nelson -8:10:47 - LMT 1884
# From Paul Eggert (1999-09-20): # From Paul Eggert (1999-09-20):
# Basic Facts: The New Territory # Basic Facts: The New Territory
# http://www.nunavut.com/basicfacts/english/basicfacts_1territory.html # http://www.nunavut.com/basicfacts/english/basicfacts_1territory.html
# (1999) reports that Pangnirtung operates on eastern time, # (1999) reports that ... Coral Harbour does not observe DST.
# and that Coral Harbour does not observe DST. We don't know when
# Pangnirtung switched to eastern time; we'll guess 1995.

# From Rives McDow (1999-11-08):
# On October 31, when the rest of Nunavut went to Central time,
# Pangnirtung wobbled. Here is the result of their wobble:
#
# The following businesses and organizations in Pangnirtung use Central Time:
#
# First Air, Power Corp, Nunavut Construction, Health Center, RCMP,
# Eastern Arctic National Parks, A & D Specialist
#
# The following businesses and organizations in Pangnirtung use Eastern Time:
#
# Hamlet office, All other businesses, Both schools, Airport operator
#
# This has made for an interesting situation there, which warranted the news.
# No one there that I spoke with seems concerned, or has plans to
# change the local methods of keeping time, as it evidently does not
# really interfere with any activities or make things difficult locally.
# They plan to celebrate New Year's turn-over twice, one hour apart,
# so it appears that the situation will last at least that long.
# The Nunavut Intergovernmental Affairs hopes that they will "come to
# their senses", but the locals evidently don't see any problem with
# the current state of affairs.

# From Michaela Rodrigue, writing in the
# Nunatsiaq News (1999-11-19):
# http://www.nunatsiaqonline.ca/archives/nunavut991130/nvt91119_17.html
# Clyde River, Pangnirtung and Sanikiluaq now operate with two time zones,
# central - or Nunavut time - for government offices, and eastern time
# for municipal offices and schools.... Igloolik [was similar but then]
# made the switch to central time on Saturday, Nov. 6.


# From Paul Eggert (2000-10-02): # From Paul Eggert (2000-10-02):
# Matthews and Vincent (1998) say the following, but we lack histories # Matthews and Vincent (1998) say the following, but we lack histories
@@ -2287,18 +2292,12 @@ Rule NT_YK 1919 only - Nov 1 0:00 0 S
Rule NT_YK 1942 only - Feb 9 2:00 1:00 W # War Rule NT_YK 1942 only - Feb 9 2:00 1:00 W # War
Rule NT_YK 1945 only - Aug 14 23:00u 1:00 P # Peace Rule NT_YK 1945 only - Aug 14 23:00u 1:00 P # Peace
Rule NT_YK 1945 only - Sep 30 2:00 0 S Rule NT_YK 1945 only - Sep 30 2:00 0 S
Rule NT_YK 1965 only - Apr lastSun 0:00 2:00 DD Rule NT_YK 1972 1986 - Apr lastSun 2:00 1:00 D
Rule NT_YK 1965 only - Oct lastSun 2:00 0 S Rule NT_YK 1972 2006 - Oct lastSun 2:00 0 S
Rule NT_YK 1980 1986 - Apr lastSun 2:00 1:00 D
Rule NT_YK 1980 2006 - Oct lastSun 2:00 0 S
Rule NT_YK 1987 2006 - Apr Sun>=1 2:00 1:00 D Rule NT_YK 1987 2006 - Apr Sun>=1 2:00 1:00 D
Rule Yukon 1965 only - Apr lastSun 0:00 2:00 DD
Rule Yukon 1965 only - Oct lastSun 2:00 0 S
# Zone NAME STDOFF RULES FORMAT [UNTIL] # Zone NAME STDOFF RULES FORMAT [UNTIL]
# aka Panniqtuuq
Zone America/Pangnirtung 0 - -00 1921 # trading post est.
-4:00 NT_YK A%sT 1995 Apr Sun>=1 2:00
-5:00 Canada E%sT 1999 Oct 31 2:00
-6:00 Canada C%sT 2000 Oct 29 2:00
-5:00 Canada E%sT
# formerly Frobisher Bay # formerly Frobisher Bay
Zone America/Iqaluit 0 - -00 1942 Aug # Frobisher Bay est. Zone America/Iqaluit 0 - -00 1942 Aug # Frobisher Bay est.
-5:00 NT_YK E%sT 1999 Oct 31 2:00 -5:00 NT_YK E%sT 1999 Oct 31 2:00
@@ -2331,13 +2330,15 @@ Zone America/Inuvik 0 - -00 1953 # Inuvik founded
-7:00 NT_YK M%sT 1980 -7:00 NT_YK M%sT 1980
-7:00 Canada M%sT -7:00 Canada M%sT
Zone America/Whitehorse -9:00:12 - LMT 1900 Aug 20 Zone America/Whitehorse -9:00:12 - LMT 1900 Aug 20
-9:00 NT_YK Y%sT 1967 May 28 0:00 -9:00 NT_YK Y%sT 1965
-8:00 NT_YK P%sT 1980 -9:00 Yukon Y%sT 1966 Feb 27 0:00
-8:00 - PST 1980
-8:00 Canada P%sT 2020 Nov 1 -8:00 Canada P%sT 2020 Nov 1
-7:00 - MST -7:00 - MST
Zone America/Dawson -9:17:40 - LMT 1900 Aug 20 Zone America/Dawson -9:17:40 - LMT 1900 Aug 20
-9:00 NT_YK Y%sT 1973 Oct 28 0:00 -9:00 NT_YK Y%sT 1965
-8:00 NT_YK P%sT 1980 -9:00 Yukon Y%sT 1973 Oct 28 0:00
-8:00 - PST 1980
-8:00 Canada P%sT 2020 Nov 1 -8:00 Canada P%sT 2020 Nov 1
-7:00 - MST -7:00 - MST


@@ -2559,6 +2560,14 @@ Zone America/Dawson -9:17:40 - LMT 1900 Aug 20
# This abolishes DST except where US DST rules are observed, # This abolishes DST except where US DST rules are observed,
# and in addition changes all of Chihuahua to -06 with no DST. # and in addition changes all of Chihuahua to -06 with no DST.


# From Heitor David Pinto (2022-11-28):
# Now the northern municipalities want to have the same time zone as the
# respective neighboring cities in the US, for example Juárez in UTC-7 with
# DST, matching El Paso, and Ojinaga in UTC-6 with DST, matching Presidio....
# the president authorized the publication of the decree for November 29,
# so the time change would occur on November 30 at 0:00.
# http://puentelibre.mx/noticia/ciudad_juarez_cambio_horario_noviembre_2022/

# Rule NAME FROM TO - IN ON AT SAVE LETTER/S # Rule NAME FROM TO - IN ON AT SAVE LETTER/S
Rule Mexico 1931 only - May 1 23:00 1:00 D Rule Mexico 1931 only - May 1 23:00 1:00 D
Rule Mexico 1931 only - Oct 1 0:00 0 S Rule Mexico 1931 only - Oct 1 0:00 0 S
@@ -2590,14 +2599,12 @@ Zone America/Merida -5:58:28 - LMT 1922 Jan 1 6:00u
-6:00 Mexico C%sT -6:00 Mexico C%sT
# Coahuila, Nuevo León, Tamaulipas (near US border) # Coahuila, Nuevo León, Tamaulipas (near US border)
# This includes the following municipalities: # This includes the following municipalities:
# in Coahuila: Ocampo, Acuña, Zaragoza, Jiménez, Piedras Negras, Nava, # in Coahuila: Acuña, Allende, Guerrero, Hidalgo, Jiménez, Morelos, Nava,
# Guerrero, Hidalgo. # Ocampo, Piedras Negras, Villa Unión, Zaragoza
# in Nuevo León: Anáhuac, Los Aldama. # in Nuevo León: Anáhuac
# in Tamaulipas: Nuevo Laredo, Guerrero, Mier, Miguel Alemán, Camargo, # in Tamaulipas: Nuevo Laredo, Guerrero, Mier, Miguel Alemán, Camargo,
# Gustavo Díaz Ordaz, Reynosa, Río Bravo, Valle Hermoso, Matamoros. # Gustavo Díaz Ordaz, Reynosa, Río Bravo, Valle Hermoso, Matamoros.
# See: Inicia mañana Horario de Verano en zona fronteriza, El Universal, # https://www.dof.gob.mx/nota_detalle.php?codigo=5670045&fecha=28/10/2022
# 2016-03-12
# http://www.eluniversal.com.mx/articulo/estados/2016/03/12/inicia-manana-horario-de-verano-en-zona-fronteriza
Zone America/Matamoros -6:30:00 - LMT 1922 Jan 1 6:00u Zone America/Matamoros -6:30:00 - LMT 1922 Jan 1 6:00u
-6:00 - CST 1988 -6:00 - CST 1988
-6:00 US C%sT 1989 -6:00 US C%sT 1989
@@ -2616,10 +2623,24 @@ Zone America/Mexico_City -6:36:36 - LMT 1922 Jan 1 7:00u
-6:00 Mexico C%sT 2001 Sep 30 2:00 -6:00 Mexico C%sT 2001 Sep 30 2:00
-6:00 - CST 2002 Feb 20 -6:00 - CST 2002 Feb 20
-6:00 Mexico C%sT -6:00 Mexico C%sT
# Chihuahua (near US border) # Chihuahua (near US border - western side)
# This includes the municipalities of Janos, Ascensión, Juárez, Guadalupe, # This includes the municipalities of Janos, Ascensión, Juárez, Guadalupe,
# Práxedis G Guerrero, Coyame del Sotol, Ojinaga, and Manuel Benavides. # and Práxedis G Guerrero.
# (See the 2016-03-12 El Universal source mentioned above.) # http://gaceta.diputados.gob.mx/PDF/65/2a022/nov/20221124-VII.pdf
Zone America/Ciudad_Juarez -7:05:56 - LMT 1922 Jan 1 7:00u
-7:00 - MST 1927 Jun 10 23:00
-6:00 - CST 1930 Nov 15
-7:00 Mexico M%sT 1932 Apr 1
-6:00 - CST 1996
-6:00 Mexico C%sT 1998
-6:00 - CST 1998 Apr Sun>=1 3:00
-7:00 Mexico M%sT 2010
-7:00 US M%sT 2022 Oct 30 2:00
-6:00 - CST 2022 Nov 30 0:00
-7:00 US M%sT
# Chihuahua (near US border - eastern side)
# The municipalities of Coyame del Sotol, Ojinaga, and Manuel Benavides.
# http://gaceta.diputados.gob.mx/PDF/65/2a022/nov/20221124-VII.pdf
Zone America/Ojinaga -6:57:40 - LMT 1922 Jan 1 7:00u Zone America/Ojinaga -6:57:40 - LMT 1922 Jan 1 7:00u
-7:00 - MST 1927 Jun 10 23:00 -7:00 - MST 1927 Jun 10 23:00
-6:00 - CST 1930 Nov 15 -6:00 - CST 1930 Nov 15
@@ -2629,7 +2650,8 @@ Zone America/Ojinaga -6:57:40 - LMT 1922 Jan 1 7:00u
-6:00 - CST 1998 Apr Sun>=1 3:00 -6:00 - CST 1998 Apr Sun>=1 3:00
-7:00 Mexico M%sT 2010 -7:00 Mexico M%sT 2010
-7:00 US M%sT 2022 Oct 30 2:00 -7:00 US M%sT 2022 Oct 30 2:00
-6:00 - CST -6:00 - CST 2022 Nov 30 0:00
-6:00 US C%sT
# Chihuahua (away from US border) # Chihuahua (away from US border)
Zone America/Chihuahua -7:04:20 - LMT 1922 Jan 1 7:00u Zone America/Chihuahua -7:04:20 - LMT 1922 Jan 1 7:00u
-7:00 - MST 1927 Jun 10 23:00 -7:00 - MST 1927 Jun 10 23:00
@@ -2651,6 +2673,18 @@ Zone America/Hermosillo -7:23:52 - LMT 1922 Jan 1 7:00u
-7:00 Mexico M%sT 1999 -7:00 Mexico M%sT 1999
-7:00 - MST -7:00 - MST


# Baja California Sur, Nayarit (except Bahía de Banderas), Sinaloa
Zone America/Mazatlan -7:05:40 - LMT 1922 Jan 1 7:00u
-7:00 - MST 1927 Jun 10 23:00
-6:00 - CST 1930 Nov 15
-7:00 Mexico M%sT 1932 Apr 1
-6:00 - CST 1942 Apr 24
-7:00 - MST 1949 Jan 14
-8:00 - PST 1970
-7:00 Mexico M%sT

# Bahía de Banderas

# From Alexander Krivenyshev (2010-04-21): # From Alexander Krivenyshev (2010-04-21):
# According to news, Bahía de Banderas (Mexican state of Nayarit) # According to news, Bahía de Banderas (Mexican state of Nayarit)
# changed time zone UTC-7 to new time zone UTC-6 on April 4, 2010 (to # changed time zone UTC-7 to new time zone UTC-6 on April 4, 2010 (to
@@ -2678,17 +2712,6 @@ Zone America/Hermosillo -7:23:52 - LMT 1922 Jan 1 7:00u
# From Arthur David Olson (2010-05-01): # From Arthur David Olson (2010-05-01):
# Use "Bahia_Banderas" to keep the name to fourteen characters. # Use "Bahia_Banderas" to keep the name to fourteen characters.


# Mazatlán
Zone America/Mazatlan -7:05:40 - LMT 1922 Jan 1 7:00u
-7:00 - MST 1927 Jun 10 23:00
-6:00 - CST 1930 Nov 15
-7:00 Mexico M%sT 1932 Apr 1
-6:00 - CST 1942 Apr 24
-7:00 - MST 1949 Jan 14
-8:00 - PST 1970
-7:00 Mexico M%sT

# Bahía de Banderas
Zone America/Bahia_Banderas -7:01:00 - LMT 1922 Jan 1 7:00u Zone America/Bahia_Banderas -7:01:00 - LMT 1922 Jan 1 7:00u
-7:00 - MST 1927 Jun 10 23:00 -7:00 - MST 1927 Jun 10 23:00
-6:00 - CST 1930 Nov 15 -6:00 - CST 1930 Nov 15
202 changes: 151 additions & 51 deletions private.h
@@ -17,6 +17,10 @@
** Thank you! ** Thank you!
*/ */


#ifndef __STDC_VERSION__
# define __STDC_VERSION__ 0
#endif

/* Define true, false and bool if they don't work out of the box. */ /* Define true, false and bool if they don't work out of the box. */
#if __STDC_VERSION__ < 199901 #if __STDC_VERSION__ < 199901
# define true 1 # define true 1
@@ -56,24 +60,13 @@
# endif # endif
#endif #endif
/* _Generic is buggy in pre-4.9 GCC. */ /* _Generic is buggy in pre-4.9 GCC. */
#if !defined HAVE_GENERIC && defined __GNUC__ #if !defined HAVE_GENERIC && defined __GNUC__ && !defined __STRICT_ANSI__
# define HAVE_GENERIC (4 < __GNUC__ + (9 <= __GNUC_MINOR__)) # define HAVE_GENERIC (4 < __GNUC__ + (9 <= __GNUC_MINOR__))
#endif #endif
#ifndef HAVE_GENERIC #ifndef HAVE_GENERIC
# define HAVE_GENERIC (201112 <= __STDC_VERSION__) # define HAVE_GENERIC (201112 <= __STDC_VERSION__)
#endif #endif


#if !defined HAVE_GETRANDOM && defined __has_include
# if __has_include(<sys/random.h>)
# define HAVE_GETRANDOM true
# else
# define HAVE_GETRANDOM false
# endif
#endif
#ifndef HAVE_GETRANDOM
# define HAVE_GETRANDOM (2 < __GLIBC__ + (25 <= __GLIBC_MINOR__))
#endif

#if !defined HAVE_GETTEXT && defined __has_include #if !defined HAVE_GETTEXT && defined __has_include
# if __has_include(<libintl.h>) # if __has_include(<libintl.h>)
# define HAVE_GETTEXT true # define HAVE_GETTEXT true
@@ -289,36 +282,36 @@
#endif #endif


/* Pre-C99 GCC compilers define __LONG_LONG_MAX__ instead of LLONG_MAX. */ /* Pre-C99 GCC compilers define __LONG_LONG_MAX__ instead of LLONG_MAX. */
#ifdef __LONG_LONG_MAX__ #if defined __LONG_LONG_MAX__ && !defined __STRICT_ANSI__
# ifndef LLONG_MAX # ifndef LLONG_MAX
# define LLONG_MAX __LONG_LONG_MAX__ # define LLONG_MAX __LONG_LONG_MAX__
# endif # endif
# ifndef LLONG_MIN # ifndef LLONG_MIN
# define LLONG_MIN (-1 - LLONG_MAX) # define LLONG_MIN (-1 - LLONG_MAX)
# endif # endif
# ifndef ULLONG_MAX
# define ULLONG_MAX (LLONG_MAX * 2ull + 1)
# endif
#endif #endif


#ifndef INT_FAST64_MAX #ifndef INT_FAST64_MAX
# ifdef LLONG_MAX # if 1 <= LONG_MAX >> 31 >> 31
typedef long long int_fast64_t; typedef long int_fast64_t;
# define INT_FAST64_MIN LLONG_MIN
# define INT_FAST64_MAX LLONG_MAX
# else
# if LONG_MAX >> 31 < 0xffffffff
Please use a compiler that supports a 64-bit integer type (or wider);
you may need to compile with "-DHAVE_STDINT_H".
# endif
typedef long int_fast64_t;
# define INT_FAST64_MIN LONG_MIN # define INT_FAST64_MIN LONG_MIN
# define INT_FAST64_MAX LONG_MAX # define INT_FAST64_MAX LONG_MAX
# else
/* If this fails, compile with -DHAVE_STDINT_H or with a better compiler. */
typedef long long int_fast64_t;
# define INT_FAST64_MIN LLONG_MIN
# define INT_FAST64_MAX LLONG_MAX
# endif # endif
#endif #endif


#ifndef PRIdFAST64 #ifndef PRIdFAST64
# if INT_FAST64_MAX == LLONG_MAX # if INT_FAST64_MAX == LONG_MAX
# define PRIdFAST64 "lld"
# else
# define PRIdFAST64 "ld" # define PRIdFAST64 "ld"
# else
# define PRIdFAST64 "lld"
# endif # endif
#endif #endif


@@ -364,32 +357,35 @@ typedef long intmax_t;
# endif # endif
#endif #endif


#ifndef PTRDIFF_MAX
# define PTRDIFF_MAX MAXVAL(ptrdiff_t, TYPE_BIT(ptrdiff_t))
#endif

#ifndef UINT_FAST32_MAX #ifndef UINT_FAST32_MAX
typedef unsigned long uint_fast32_t; typedef unsigned long uint_fast32_t;
#endif #endif


#ifndef UINT_FAST64_MAX #ifndef UINT_FAST64_MAX
# if defined ULLONG_MAX || defined __LONG_LONG_MAX__ # if 3 <= ULONG_MAX >> 31 >> 31
typedef unsigned long long uint_fast64_t; typedef unsigned long uint_fast64_t;
# define UINT_FAST64_MAX ULONG_MAX
# else # else
# if ULONG_MAX >> 31 >> 1 < 0xffffffff /* If this fails, compile with -DHAVE_STDINT_H or with a better compiler. */
Please use a compiler that supports a 64-bit integer type (or wider); typedef unsigned long long uint_fast64_t;
you may need to compile with "-DHAVE_STDINT_H". # define UINT_FAST64_MAX ULLONG_MAX
# endif
typedef unsigned long uint_fast64_t;
# endif # endif
#endif #endif


#ifndef UINTMAX_MAX #ifndef UINTMAX_MAX
# if defined ULLONG_MAX || defined __LONG_LONG_MAX__ # ifdef ULLONG_MAX
typedef unsigned long long uintmax_t; typedef unsigned long long uintmax_t;
# else # else
typedef unsigned long uintmax_t; typedef unsigned long uintmax_t;
# endif # endif
#endif #endif


#ifndef PRIuMAX #ifndef PRIuMAX
# if defined ULLONG_MAX || defined __LONG_LONG_MAX__ # ifdef ULLONG_MAX
# define PRIuMAX "llu" # define PRIuMAX "llu"
# else # else
# define PRIuMAX "lu" # define PRIuMAX "lu"
@@ -400,23 +396,114 @@ typedef unsigned long uintmax_t;
# define SIZE_MAX ((size_t) -1) # define SIZE_MAX ((size_t) -1)
#endif #endif


/* Support ckd_add, ckd_sub, ckd_mul on C23 or recent-enough GCC-like
hosts, unless compiled with -DHAVE_STDCKDINT_H=0 or with pre-C23 EDG. */
#if !defined HAVE_STDCKDINT_H && defined __has_include
# if __has_include(<stdckdint.h>)
# define HAVE_STDCKDINT_H true
# endif
#endif
#ifdef HAVE_STDCKDINT_H
# if HAVE_STDCKDINT_H
# include <stdckdint.h>
# endif
#elif defined __EDG__
/* Do nothing, to work around EDG bug <https://bugs.gnu.org/53256>. */
#elif defined __has_builtin
# if __has_builtin(__builtin_add_overflow)
# define ckd_add(r, a, b) __builtin_add_overflow(a, b, r)
# endif
# if __has_builtin(__builtin_sub_overflow)
# define ckd_sub(r, a, b) __builtin_sub_overflow(a, b, r)
# endif
# if __has_builtin(__builtin_mul_overflow)
# define ckd_mul(r, a, b) __builtin_mul_overflow(a, b, r)
# endif
#elif 7 <= __GNUC__
# define ckd_add(r, a, b) __builtin_add_overflow(a, b, r)
# define ckd_sub(r, a, b) __builtin_sub_overflow(a, b, r)
# define ckd_mul(r, a, b) __builtin_mul_overflow(a, b, r)
#endif

#if 3 <= __GNUC__ #if 3 <= __GNUC__
# define ATTRIBUTE_CONST __attribute__((const)) # define ATTRIBUTE_MALLOC __attribute__((malloc))
# define ATTRIBUTE_MALLOC __attribute__((__malloc__)) # define ATTRIBUTE_FORMAT(spec) __attribute__((format spec))
# define ATTRIBUTE_PURE __attribute__((__pure__))
# define ATTRIBUTE_FORMAT(spec) __attribute__((__format__ spec))
#else #else
# define ATTRIBUTE_CONST /* empty */
# define ATTRIBUTE_MALLOC /* empty */ # define ATTRIBUTE_MALLOC /* empty */
# define ATTRIBUTE_PURE /* empty */
# define ATTRIBUTE_FORMAT(spec) /* empty */ # define ATTRIBUTE_FORMAT(spec) /* empty */
#endif #endif


#if !defined _Noreturn && __STDC_VERSION__ < 201112 #if (defined __has_c_attribute \
# if 2 < __GNUC__ + (8 <= __GNUC_MINOR__) && (202311 <= __STDC_VERSION__ || !defined __STRICT_ANSI__))
# define _Noreturn __attribute__((__noreturn__)) # define HAVE_HAS_C_ATTRIBUTE true
#else
# define HAVE_HAS_C_ATTRIBUTE false
#endif

#if HAVE_HAS_C_ATTRIBUTE
# if __has_c_attribute(fallthrough)
# define ATTRIBUTE_FALLTHROUGH [[fallthrough]]
# endif
#endif
#ifndef ATTRIBUTE_FALLTHROUGH
# if 7 <= __GNUC__
# define ATTRIBUTE_FALLTHROUGH __attribute__((fallthrough))
# else
# define ATTRIBUTE_FALLTHROUGH ((void) 0)
# endif
#endif

#if HAVE_HAS_C_ATTRIBUTE
# if __has_c_attribute(maybe_unused)
# define ATTRIBUTE_MAYBE_UNUSED [[maybe_unused]]
# endif
#endif
#ifndef ATTRIBUTE_MAYBE_UNUSED
# if 2 < __GNUC__ + (7 <= __GNUC_MINOR__)
# define ATTRIBUTE_MAYBE_UNUSED __attribute__((unused))
# else
# define ATTRIBUTE_MAYBE_UNUSED /* empty */
# endif
#endif

#if HAVE_HAS_C_ATTRIBUTE
# if __has_c_attribute(noreturn)
# define ATTRIBUTE_NORETURN [[noreturn]]
# endif
#endif
#ifndef ATTRIBUTE_NORETURN
# if 201112 <= __STDC_VERSION__
# define ATTRIBUTE_NORETURN _Noreturn
# elif 2 < __GNUC__ + (8 <= __GNUC_MINOR__)
# define ATTRIBUTE_NORETURN __attribute__((noreturn))
# else # else
# define _Noreturn # define ATTRIBUTE_NORETURN /* empty */
# endif
#endif

#if HAVE_HAS_C_ATTRIBUTE
# if __has_c_attribute(reproducible)
# define ATTRIBUTE_REPRODUCIBLE [[reproducible]]
# endif
#endif
#ifndef ATTRIBUTE_REPRODUCIBLE
# if 3 <= __GNUC__
# define ATTRIBUTE_REPRODUCIBLE __attribute__((pure))
# else
# define ATTRIBUTE_REPRODUCIBLE /* empty */
# endif
#endif

#if HAVE_HAS_C_ATTRIBUTE
# if __has_c_attribute(unsequenced)
# define ATTRIBUTE_UNSEQUENCED [[unsequenced]]
# endif
#endif
#ifndef ATTRIBUTE_UNSEQUENCED
# if 3 <= __GNUC__
# define ATTRIBUTE_UNSEQUENCED __attribute__((const))
# else
# define ATTRIBUTE_UNSEQUENCED /* empty */
# endif # endif
#endif #endif


@@ -541,7 +628,7 @@ char *asctime(struct tm const *);
char *asctime_r(struct tm const *restrict, char *restrict); char *asctime_r(struct tm const *restrict, char *restrict);
char *ctime(time_t const *); char *ctime(time_t const *);
char *ctime_r(time_t const *, char *); char *ctime_r(time_t const *, char *);
double difftime(time_t, time_t) ATTRIBUTE_CONST; double difftime(time_t, time_t) ATTRIBUTE_UNSEQUENCED;
size_t strftime(char *restrict, size_t, char const *restrict, size_t strftime(char *restrict, size_t, char const *restrict,
struct tm const *restrict); struct tm const *restrict);
# if HAVE_STRFTIME_L # if HAVE_STRFTIME_L
@@ -554,9 +641,24 @@ struct tm *localtime(time_t const *);
struct tm *localtime_r(time_t const *restrict, struct tm *restrict); struct tm *localtime_r(time_t const *restrict, struct tm *restrict);
time_t mktime(struct tm *); time_t mktime(struct tm *);
time_t time(time_t *); time_t time(time_t *);
time_t timegm(struct tm *);
void tzset(void); void tzset(void);
#endif #endif


#ifndef HAVE_DECL_TIMEGM
# if (202311 <= __STDC_VERSION__ \
|| defined __GLIBC__ || defined __tm_zone /* musl */ \
|| defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ \
|| (defined __APPLE__ && defined __MACH__))
# define HAVE_DECL_TIMEGM true
# else
# define HAVE_DECL_TIMEGM false
# endif
#endif
#if !HAVE_DECL_TIMEGM && !defined timegm
time_t timegm(struct tm *);
#endif

#if !HAVE_DECL_ASCTIME_R && !defined asctime_r #if !HAVE_DECL_ASCTIME_R && !defined asctime_r
extern char *asctime_r(struct tm const *restrict, char *restrict); extern char *asctime_r(struct tm const *restrict, char *restrict);
#endif #endif
@@ -593,9 +695,6 @@ extern long altzone;
# if TZ_TIME_T || !defined offtime # if TZ_TIME_T || !defined offtime
struct tm *offtime(time_t const *, long); struct tm *offtime(time_t const *, long);
# endif # endif
# if TZ_TIME_T || !defined timegm
time_t timegm(struct tm *);
# endif
# if TZ_TIME_T || !defined timelocal # if TZ_TIME_T || !defined timelocal
time_t timelocal(struct tm *); time_t timelocal(struct tm *);
# endif # endif
@@ -613,6 +712,7 @@ time_t posix2time(time_t);
/* Infer TM_ZONE on systems where this information is known, but suppress /* Infer TM_ZONE on systems where this information is known, but suppress
guessing if NO_TM_ZONE is defined. Similarly for TM_GMTOFF. */ guessing if NO_TM_ZONE is defined. Similarly for TM_GMTOFF. */
#if (defined __GLIBC__ \ #if (defined __GLIBC__ \
|| defined __tm_zone /* musl */ \
|| defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ \ || defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ \
|| (defined __APPLE__ && defined __MACH__)) || (defined __APPLE__ && defined __MACH__))
# if !defined TM_GMTOFF && !defined NO_TM_GMTOFF # if !defined TM_GMTOFF && !defined NO_TM_GMTOFF
@@ -640,10 +740,10 @@ timezone_t tzalloc(char const *);
void tzfree(timezone_t); void tzfree(timezone_t);
# ifdef STD_INSPIRED # ifdef STD_INSPIRED
# if TZ_TIME_T || !defined posix2time_z # if TZ_TIME_T || !defined posix2time_z
time_t posix2time_z(timezone_t, time_t) ATTRIBUTE_PURE; time_t posix2time_z(timezone_t, time_t) ATTRIBUTE_REPRODUCIBLE;
# endif # endif
# if TZ_TIME_T || !defined time2posix_z # if TZ_TIME_T || !defined time2posix_z
time_t time2posix_z(timezone_t, time_t) ATTRIBUTE_PURE; time_t time2posix_z(timezone_t, time_t) ATTRIBUTE_REPRODUCIBLE;
# endif # endif
# endif # endif
#endif #endif
9 changes: 7 additions & 2 deletions southamerica
@@ -1418,9 +1418,14 @@ Zone Antarctica/Palmer 0 - -00 1965
# Milne gives 4:56:16.4 for Bogotá time in 1899. He writes, # Milne gives 4:56:16.4 for Bogotá time in 1899. He writes,
# "A variation of fifteen minutes in the public clocks of Bogota is not rare." # "A variation of fifteen minutes in the public clocks of Bogota is not rare."


# From Alois Treindl (2022-11-10):
# End of time change in Colombia 1993 ... should be 6 February 24h ...
# DECRETO 267 DE 1993
# https://www.suin-juriscol.gov.co/viewDocument.asp?ruta=Decretos/1061335

# Rule NAME FROM TO - IN ON AT SAVE LETTER/S # Rule NAME FROM TO - IN ON AT SAVE LETTER/S
Rule CO 1992 only - May 3 0:00 1:00 - Rule CO 1992 only - May 3 0:00 1:00 -
Rule CO 1993 only - Apr 4 0:00 0 - Rule CO 1993 only - Feb 6 24:00 0 -
# Zone NAME STDOFF RULES FORMAT [UNTIL] # Zone NAME STDOFF RULES FORMAT [UNTIL]
#STDOFF -4:56:16.4 #STDOFF -4:56:16.4
Zone America/Bogota -4:56:16 - LMT 1884 Mar 13 Zone America/Bogota -4:56:16 - LMT 1884 Mar 13
21 changes: 15 additions & 6 deletions strftime.c
@@ -117,7 +117,7 @@ static char * _yconv(int, int, bool, bool, char *, char const *);
#if HAVE_STRFTIME_L #if HAVE_STRFTIME_L
size_t size_t
strftime_l(char *s, size_t maxsize, char const *format, struct tm const *t, strftime_l(char *s, size_t maxsize, char const *format, struct tm const *t,
locale_t locale) ATTRIBUTE_MAYBE_UNUSED locale_t locale)
{ {
/* Just call strftime, as only the C locale is supported. */ /* Just call strftime, as only the C locale is supported. */
return strftime(s, maxsize, format, t); return strftime(s, maxsize, format, t);
@@ -319,12 +319,21 @@ _fmt(const char *format, const struct tm *t, char *pt,
time_t) + 1]; time_t) + 1];
time_t mkt; time_t mkt;


tm = *t; tm.tm_sec = t->tm_sec;
tm.tm_min = t->tm_min;
tm.tm_hour = t->tm_hour;
tm.tm_mday = t->tm_mday;
tm.tm_mon = t->tm_mon;
tm.tm_year = t->tm_year;
tm.tm_isdst = t->tm_isdst;
#if defined TM_GMTOFF && ! UNINIT_TRAP
tm.TM_GMTOFF = t->TM_GMTOFF;
#endif
mkt = mktime(&tm); mkt = mktime(&tm);
/* There is no portable, definitive /* If mktime fails, %s expands to the
test for whether whether mktime value of (time_t) -1 as a failure
succeeded, so treat (time_t) -1 as marker; this is better in practice
the success that it might be. */ than strftime failing. */
if (TYPE_SIGNED(time_t)) { if (TYPE_SIGNED(time_t)) {
intmax_t n = mkt; intmax_t n = mkt;
sprintf(buf, "%"PRIdMAX, n); sprintf(buf, "%"PRIdMAX, n);
1 change: 0 additions & 1 deletion theory.html
@@ -60,7 +60,6 @@ <h2 id="scope">Scope of the <code><abbr>tz</abbr></code> database</h2>
American mountain time zone can choose from the timezones American mountain time zone can choose from the timezones
<code>America/Denver</code> which observes US-style daylight saving <code>America/Denver</code> which observes US-style daylight saving
time (<abbr>DST</abbr>), time (<abbr>DST</abbr>),
<code>America/Mazatlan</code> which observes Mexican-style <abbr>DST</abbr>,
and <code>America/Phoenix</code> which does not observe <abbr>DST</abbr>. and <code>America/Phoenix</code> which does not observe <abbr>DST</abbr>.
Applications that also deal with past timestamps in the mountain time Applications that also deal with past timestamps in the mountain time
zone can choose from over a dozen timezones, such as zone can choose from over a dozen timezones, such as
16 changes: 8 additions & 8 deletions time2posix.3
@@ -1,9 +1,11 @@
.TH TIME2POSIX 3 .\" This file is in the public domain, so clarified as of
.\" 1996-06-05 by Arthur David Olson.
.TH time2posix 3
.SH NAME .SH NAME
time2posix, posix2time \- convert seconds since the Epoch time2posix, posix2time \- convert seconds since the Epoch
.SH SYNOPSIS .SH SYNOPSIS
.nf .nf
.ie \n(.g .ds - \f(CW-\fP .ie \n(.g .ds - \f(CR-\fP
.el .ds - \- .el .ds - \-
.B #include <time.h> .B #include <time.h>
.PP .PP
@@ -58,7 +60,7 @@ expression for directly computing a time_t value from a given date/time,
and the same relationship is assumed by some and the same relationship is assumed by some
(usually older) (usually older)
applications. applications.
Any programs creating/dissecting time_t's Any programs creating/dissecting time_t values
using such a relationship will typically not handle intervals using such a relationship will typically not handle intervals
over leap seconds correctly. over leap seconds correctly.
.PP .PP
@@ -93,7 +95,7 @@ Both of these are good indicators of the inferiority of the
POSIX representation. POSIX representation.
.PP .PP
The following table summarizes the relationship between a time The following table summarizes the relationship between a time
T and it's conversion to, T and its conversion to,
and back from, and back from,
the POSIX representation over the leap second inserted at the end of June, the POSIX representation over the leap second inserted at the end of June,
1993. 1993.
@@ -117,8 +119,8 @@ DATE TIME T X=time2posix(T) posix2time(X)
.fi .fi
.PP .PP
If leap-second support is not enabled, If leap-second support is not enabled,
local time_t's and local time_t and
POSIX time_t's are equivalent, POSIX time_t values are equivalent,
and both and both
.B time2posix .B time2posix
and and
@@ -129,5 +131,3 @@ difftime(3),
localtime(3), localtime(3),
mktime(3), mktime(3),
time(2) time(2)
.\" This file is in the public domain, so clarified as of
.\" 1996-06-05 by Arthur David Olson.
6 changes: 3 additions & 3 deletions tzfile.5
@@ -1,3 +1,5 @@
.\" This file is in the public domain, so clarified as of
.\" 1996-06-05 by Arthur David Olson.
.TH TZFILE 5 .TH TZFILE 5
.SH NAME .SH NAME
tzfile \- timezone information tzfile \- timezone information
@@ -9,7 +11,7 @@ tzfile \- timezone information
.de q .de q
\\$3\*(lq\\$1\*(rq\\$2 \\$3\*(lq\\$1\*(rq\\$2
.. ..
.ie \n(.g .ds - \f(CW-\fP .ie \n(.g .ds - \f(CR-\fP
.el .ds - \- .el .ds - \-
The timezone information files used by The timezone information files used by
.BR tzset (3) .BR tzset (3)
@@ -492,5 +494,3 @@ Internet RFC 8536
.UR https://\:doi.org/\:10.17487/\:RFC8536 .UR https://\:doi.org/\:10.17487/\:RFC8536
doi:10.17487/RFC8536 doi:10.17487/RFC8536
.UE . .UE .
.\" This file is in the public domain, so clarified as of
.\" 1996-06-05 by Arthur David Olson.
6 changes: 3 additions & 3 deletions tzselect.8
@@ -1,8 +1,10 @@
.\" This file is in the public domain, so clarified as of
.\" 2009-05-17 by Arthur David Olson.
.TH TZSELECT 8 .TH TZSELECT 8
.SH NAME .SH NAME
tzselect \- select a timezone tzselect \- select a timezone
.SH SYNOPSIS .SH SYNOPSIS
.ie \n(.g .ds - \f(CW-\fP .ie \n(.g .ds - \f(CR-\fP
.el .ds - \- .el .ds - \-
.ds d " degrees .ds d " degrees
.ds m " minutes .ds m " minutes
@@ -121,5 +123,3 @@ newctime(3), tzfile(5), zdump(8), zic(8)
Applications should not assume that Applications should not assume that
.BR tzselect 's .BR tzselect 's
output matches the user's political preferences. output matches the user's political preferences.
.\" This file is in the public domain, so clarified as of
.\" 2009-05-17 by Arthur David Olson.
12 changes: 6 additions & 6 deletions zdump.8
@@ -1,4 +1,6 @@
.TH ZDUMP 8 .\" This file is in the public domain, so clarified as of
.\" 2009-05-17 by Arthur David Olson.
.TH zdump 8
.SH NAME .SH NAME
zdump \- timezone dumper zdump \- timezone dumper
.SH SYNOPSIS .SH SYNOPSIS
@@ -16,7 +18,7 @@ zdump \- timezone dumper
.de q .de q
\\$3\*(lq\\$1\*(rq\\$2 \\$3\*(lq\\$1\*(rq\\$2
.. ..
.ie \n(.g .ds - \f(CW-\fP .ie \n(.g .ds - \f(CR-\fP
.el .ds - \- .el .ds - \-
The The
.B zdump .B zdump
@@ -149,7 +151,7 @@ Here is an example of the output, with the leading empty line omitted.
tabbed columns line up.) tabbed columns line up.)
.nf .nf
.sp .sp
.if \n(.g .ft CW .if \n(.g .ft CR
.if t .in +.5i .if t .in +.5i
.if n .in +2 .if n .in +2
.nr w \w'1896-01-13 'u+\n(.i .nr w \w'1896-01-13 'u+\n(.i
@@ -182,7 +184,7 @@ UT, a standard time abbreviated HST.
Here are excerpts from another example: Here are excerpts from another example:
.nf .nf
.sp .sp
.if \n(.g .ft CW .if \n(.g .ft CR
.if t .in +.5i .if t .in +.5i
.if n .in +2 .if n .in +2
TZ="Europe/Astrakhan" TZ="Europe/Astrakhan"
@@ -227,5 +229,3 @@ introduction of UTC is problematic.
.SH SEE ALSO .SH SEE ALSO
.BR tzfile (5), .BR tzfile (5),
.BR zic (8) .BR zic (8)
.\" This file is in the public domain, so clarified as of
.\" 2009-05-17 by Arthur David Olson.
103 changes: 62 additions & 41 deletions zdump.c
@@ -84,20 +84,20 @@ static time_t const absolute_max_time =
? (((time_t) 1 << atime_shift) - 1 + ((time_t) 1 << atime_shift)) ? (((time_t) 1 << atime_shift) - 1 + ((time_t) 1 << atime_shift))
: -1); : -1);
static int longest; static int longest;
static char * progname; static char const *progname;
static bool warned; static bool warned;
static bool errout; static bool errout;


static char const *abbr(struct tm const *); static char const *abbr(struct tm const *);
static intmax_t delta(struct tm *, struct tm *) ATTRIBUTE_PURE; static intmax_t delta(struct tm *, struct tm *) ATTRIBUTE_REPRODUCIBLE;
static void dumptime(struct tm const *); static void dumptime(struct tm const *);
static time_t hunt(timezone_t, char *, time_t, time_t, bool); static time_t hunt(timezone_t, time_t, time_t, bool);
static void show(timezone_t, char *, time_t, bool); static void show(timezone_t, char *, time_t, bool);
static void showextrema(timezone_t, char *, time_t, struct tm *, time_t); static void showextrema(timezone_t, char *, time_t, struct tm *, time_t);
static void showtrans(char const *, struct tm const *, time_t, char const *, static void showtrans(char const *, struct tm const *, time_t, char const *,
char const *); char const *);
static const char *tformat(void); static const char *tformat(void);
static time_t yeartot(intmax_t) ATTRIBUTE_PURE; static time_t yeartot(intmax_t) ATTRIBUTE_REPRODUCIBLE;


/* Is C an ASCII digit? */ /* Is C an ASCII digit? */
static bool static bool
@@ -125,16 +125,28 @@ is_alpha(char a)
} }
} }


/* Return A + B, exiting if the result would overflow. */ static ATTRIBUTE_NORETURN void
static size_t size_overflow(void)
{
fprintf(stderr, _("%s: size overflow\n"), progname);
exit(EXIT_FAILURE);
}

/* Return A + B, exiting if the result would overflow either ptrdiff_t
or size_t. */
static ATTRIBUTE_REPRODUCIBLE ptrdiff_t
sumsize(size_t a, size_t b) sumsize(size_t a, size_t b)
{ {
size_t sum = a + b; #ifdef ckd_add
if (sum < a) { ptrdiff_t sum;
fprintf(stderr, _("%s: size overflow\n"), progname); if (!ckd_add(&sum, a, b) && sum <= SIZE_MAX)
exit(EXIT_FAILURE); return sum;
} #else
return sum; ptrdiff_t sum_max = min(PTRDIFF_MAX, SIZE_MAX);
if (a <= sum_max && b <= sum_max - a)
return a + b;
#endif
size_overflow();
} }


/* Return a pointer to a newly allocated buffer of size SIZE, exiting /* Return a pointer to a newly allocated buffer of size SIZE, exiting
@@ -234,22 +246,30 @@ tzalloc(char const *val)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
tzset(); tzset();
return NULL; return &optarg; /* Any valid non-null char ** will do. */
# else # else
enum { TZeqlen = 3 }; enum { TZeqlen = 3 };
static char const TZeq[TZeqlen] = "TZ="; static char const TZeq[TZeqlen] = "TZ=";
static char **fakeenv; static char **fakeenv;
static size_t fakeenv0size; static ptrdiff_t fakeenv0size;
void *freeable = NULL; void *freeable = NULL;
char **env = fakeenv, **initial_environ; char **env = fakeenv, **initial_environ;
size_t valsize = strlen(val) + 1; size_t valsize = strlen(val) + 1;
if (fakeenv0size < valsize) { if (fakeenv0size < valsize) {
char **e = environ, **to; char **e = environ, **to;
ptrdiff_t initial_nenvptrs; /* Counting the trailing NULL pointer. */ ptrdiff_t initial_nenvptrs = 1; /* Counting the trailing NULL pointer. */


while (*e++) while (*e++) {
continue; # ifdef ckd_add
initial_nenvptrs = e - environ; if (ckd_add(&initial_nenvptrs, initial_envptrs, 1)
|| SIZE_MAX < initial_envptrs)
size_overflow();
# else
if (initial_nenvptrs == min(PTRDIFF_MAX, SIZE_MAX) / sizeof *environ)
size_overflow();
initial_nenvptrs++;
# endif
}
fakeenv0size = sumsize(valsize, valsize); fakeenv0size = sumsize(valsize, valsize);
fakeenv0size = max(fakeenv0size, 64); fakeenv0size = max(fakeenv0size, 64);
freeable = env; freeable = env;
@@ -385,7 +405,7 @@ abbrok(const char *const abbrp, const char *const zone)
return the abbreviation. Get the abbreviation from TMP. return the abbreviation. Get the abbreviation from TMP.
Exit on memory allocation failure. */ Exit on memory allocation failure. */
static char const * static char const *
saveabbr(char **buf, size_t *bufalloc, struct tm const *tmp) saveabbr(char **buf, ptrdiff_t *bufalloc, struct tm const *tmp)
{ {
char const *ab = abbr(tmp); char const *ab = abbr(tmp);
if (HAVE_LOCALTIME_RZ) if (HAVE_LOCALTIME_RZ)
@@ -442,7 +462,7 @@ main(int argc, char *argv[])
{ {
/* These are static so that they're initially zero. */ /* These are static so that they're initially zero. */
static char * abbrev; static char * abbrev;
static size_t abbrevsize; static ptrdiff_t abbrevsize;


register int i; register int i;
register bool vflag; register bool vflag;
@@ -463,7 +483,7 @@ main(int argc, char *argv[])
# endif /* defined TEXTDOMAINDIR */ # endif /* defined TEXTDOMAINDIR */
textdomain(TZ_DOMAIN); textdomain(TZ_DOMAIN);
#endif /* HAVE_GETTEXT */ #endif /* HAVE_GETTEXT */
progname = argv[0]; progname = argv[0] ? argv[0] : "zdump";
for (i = 1; i < argc; ++i) for (i = 1; i < argc; ++i)
if (strcmp(argv[i], "--version") == 0) { if (strcmp(argv[i], "--version") == 0) {
printf("zdump %s%s\n", PKGVERSION, TZVERSION); printf("zdump %s%s\n", PKGVERSION, TZVERSION);
@@ -483,7 +503,7 @@ main(int argc, char *argv[])
case -1: case -1:
if (! (optind == argc - 1 && strcmp(argv[optind], "=") == 0)) if (! (optind == argc - 1 && strcmp(argv[optind], "=") == 0))
goto arg_processing_done; goto arg_processing_done;
/* Fall through. */ ATTRIBUTE_FALLTHROUGH;
default: default:
usage(stderr, EXIT_FAILURE); usage(stderr, EXIT_FAILURE);
} }
@@ -607,7 +627,7 @@ main(int argc, char *argv[])
|| (ab && (delta(&newtm, &tm) != newt - t || (ab && (delta(&newtm, &tm) != newt - t
|| newtm.tm_isdst != tm.tm_isdst || newtm.tm_isdst != tm.tm_isdst
|| strcmp(abbr(&newtm), ab) != 0))) { || strcmp(abbr(&newtm), ab) != 0))) {
newt = hunt(tz, argv[i], t, newt, false); newt = hunt(tz, t, newt, false);
newtmp = localtime_rz(tz, &newt, &newtm); newtmp = localtime_rz(tz, &newt, &newtm);
newtm_ok = newtmp != NULL; newtm_ok = newtmp != NULL;
if (iflag) if (iflag)
@@ -687,18 +707,18 @@ yeartot(intmax_t y)
return t; return t;
} }


/* Search for a discontinuity in timezone TZ with name NAME, in the /* Search for a discontinuity in timezone TZ, in the
timestamps ranging from LOT through HIT. LOT and HIT disagree timestamps ranging from LOT through HIT. LOT and HIT disagree
about some aspect of timezone. If ONLY_OK, search only for about some aspect of timezone. If ONLY_OK, search only for
definedness changes, i.e., localtime succeeds on one side of the definedness changes, i.e., localtime succeeds on one side of the
transition but fails on the other side. Return the timestamp just transition but fails on the other side. Return the timestamp just
before the transition from LOT's settings. */ before the transition from LOT's settings. */


static time_t static time_t
hunt(timezone_t tz, char *name, time_t lot, time_t hit, bool only_ok) hunt(timezone_t tz, time_t lot, time_t hit, bool only_ok)
{ {
static char * loab; static char * loab;
static size_t loabsize; static ptrdiff_t loabsize;
struct tm lotm; struct tm lotm;
struct tm tm; struct tm tm;


@@ -787,7 +807,8 @@ adjusted_yday(struct tm const *a, struct tm const *b)
my_gmtime_r and use its result instead of B. Otherwise, B is the my_gmtime_r and use its result instead of B. Otherwise, B is the
possibly nonnull result of an earlier call to my_gmtime_r. */ possibly nonnull result of an earlier call to my_gmtime_r. */
static long static long
gmtoff(struct tm const *a, time_t *t, struct tm const *b) gmtoff(struct tm const *a, ATTRIBUTE_MAYBE_UNUSED time_t *t,
ATTRIBUTE_MAYBE_UNUSED struct tm const *b)
{ {
#ifdef TM_GMTOFF #ifdef TM_GMTOFF
return a->TM_GMTOFF; return a->TM_GMTOFF;
@@ -858,7 +879,7 @@ static void
showextrema(timezone_t tz, char *zone, time_t lo, struct tm *lotmp, time_t hi) showextrema(timezone_t tz, char *zone, time_t lo, struct tm *lotmp, time_t hi)
{ {
struct tm localtm[2], gmtm[2]; struct tm localtm[2], gmtm[2];
time_t t, boundary = hunt(tz, zone, lo, hi, true); time_t t, boundary = hunt(tz, lo, hi, true);
bool old = false; bool old = false;
hi = (SECSPERDAY < hi - boundary hi = (SECSPERDAY < hi - boundary
? boundary + SECSPERDAY ? boundary + SECSPERDAY
@@ -937,7 +958,7 @@ my_snprintf(char *s, size_t size, char const *format, ...)
fit, return the length that the string would have been if it had fit, return the length that the string would have been if it had
fit; do not overrun the output buffer. */ fit; do not overrun the output buffer. */
static int static int
format_local_time(char *buf, size_t size, struct tm const *tm) format_local_time(char *buf, ptrdiff_t size, struct tm const *tm)
{ {
int ss = tm->tm_sec, mm = tm->tm_min, hh = tm->tm_hour; int ss = tm->tm_sec, mm = tm->tm_min, hh = tm->tm_hour;
return (ss return (ss
@@ -960,7 +981,7 @@ format_local_time(char *buf, size_t size, struct tm const *tm)
the length that the string would have been if it had fit; do not the length that the string would have been if it had fit; do not
overrun the output buffer. */ overrun the output buffer. */
static int static int
format_utc_offset(char *buf, size_t size, struct tm const *tm, time_t t) format_utc_offset(char *buf, ptrdiff_t size, struct tm const *tm, time_t t)
{ {
long off = gmtoff(tm, &t, NULL); long off = gmtoff(tm, &t, NULL);
char sign = ((off < 0 char sign = ((off < 0
@@ -989,11 +1010,11 @@ format_utc_offset(char *buf, size_t size, struct tm const *tm, time_t t)
If the representation's length is less than SIZE, return the If the representation's length is less than SIZE, return the
length; the representation is not null terminated. Otherwise length; the representation is not null terminated. Otherwise
return SIZE, to indicate that BUF is too small. */ return SIZE, to indicate that BUF is too small. */
static size_t static ptrdiff_t
format_quoted_string(char *buf, size_t size, char const *p) format_quoted_string(char *buf, ptrdiff_t size, char const *p)
{ {
char *b = buf; char *b = buf;
size_t s = size; ptrdiff_t s = size;
if (!s) if (!s)
return size; return size;
*b++ = '"', s--; *b++ = '"', s--;
@@ -1031,11 +1052,11 @@ format_quoted_string(char *buf, size_t size, char const *p)
and omit any trailing tabs. */ and omit any trailing tabs. */


static bool static bool
istrftime(char *buf, size_t size, char const *time_fmt, istrftime(char *buf, ptrdiff_t size, char const *time_fmt,
struct tm const *tm, time_t t, char const *ab, char const *zone_name) struct tm const *tm, time_t t, char const *ab, char const *zone_name)
{ {
char *b = buf; char *b = buf;
size_t s = size; ptrdiff_t s = size;
char const *f = time_fmt, *p; char const *f = time_fmt, *p;


for (p = f; ; p++) for (p = f; ; p++)
@@ -1044,9 +1065,9 @@ istrftime(char *buf, size_t size, char const *time_fmt,
else if (!*p else if (!*p
|| (*p == '%' || (*p == '%'
&& (p[1] == 'f' || p[1] == 'L' || p[1] == 'Q'))) { && (p[1] == 'f' || p[1] == 'L' || p[1] == 'Q'))) {
size_t formatted_len; ptrdiff_t formatted_len;
size_t f_prefix_len = p - f; ptrdiff_t f_prefix_len = p - f;
size_t f_prefix_copy_size = p - f + 2; ptrdiff_t f_prefix_copy_size = sumsize(f_prefix_len, 2);
char fbuf[100]; char fbuf[100];
bool oversized = sizeof fbuf <= f_prefix_copy_size; bool oversized = sizeof fbuf <= f_prefix_copy_size;
char *f_prefix_copy = oversized ? xmalloc(f_prefix_copy_size) : fbuf; char *f_prefix_copy = oversized ? xmalloc(f_prefix_copy_size) : fbuf;
@@ -1078,7 +1099,7 @@ istrftime(char *buf, size_t size, char const *time_fmt,
b += offlen, s -= offlen; b += offlen, s -= offlen;
if (show_abbr) { if (show_abbr) {
char const *abp; char const *abp;
size_t len; ptrdiff_t len;
if (s <= 1) if (s <= 1)
return false; return false;
*b++ = '\t', s--; *b++ = '\t', s--;
@@ -1117,7 +1138,7 @@ showtrans(char const *time_fmt, struct tm const *tm, time_t t, char const *ab,
putchar('\n'); putchar('\n');
} else { } else {
char stackbuf[1000]; char stackbuf[1000];
size_t size = sizeof stackbuf; ptrdiff_t size = sizeof stackbuf;
char *buf = stackbuf; char *buf = stackbuf;
char *bufalloc = NULL; char *bufalloc = NULL;
while (! istrftime(buf, size, time_fmt, tm, t, ab, zone_name)) { while (! istrftime(buf, size, time_fmt, tm, t, ab, zone_name)) {
12 changes: 7 additions & 5 deletions zic.8
@@ -1,4 +1,6 @@
.TH ZIC 8 .\" This file is in the public domain, so clarified as of
.\" 2009-05-17 by Arthur David Olson.
.TH zic 8
.SH NAME .SH NAME
zic \- timezone compiler zic \- timezone compiler
.SH SYNOPSIS .SH SYNOPSIS
@@ -22,7 +24,7 @@ zic \- timezone compiler
.el .ds > \(ra .el .ds > \(ra
.ie \n(.g \{\ .ie \n(.g \{\
. ds : \: . ds : \:
. ds - \f(CW-\fP . ds - \f(CR-\fP
.\} .\}
.el \{\ .el \{\
. ds : . ds :
@@ -347,7 +349,9 @@ nor
.q + . .q + .
To allow for future extensions, To allow for future extensions,
an unquoted name should not contain characters from the set an unquoted name should not contain characters from the set
.q !$%&'()*,/:;<=>?@[\e]^`{|}~ . .ie \n(.g .q \f(CR!$%&\(aq()*,/:;<=>?@[\e]\(ha\(ga{|}\(ti\fP .
.el .ie t .q \f(CW!$%&'()*,/:;<=>?@[\e]^\(ga{|}~\fP .
.el .q !$%&'()*,/:;<=>?@[\e]^`{|}~ .
.TP .TP
.B FROM .B FROM
Gives the first year in which the rule applies. Gives the first year in which the rule applies.
@@ -894,5 +898,3 @@ specifying transition instants using universal time.
.SH SEE ALSO .SH SEE ALSO
.BR tzfile (5), .BR tzfile (5),
.BR zdump (8) .BR zdump (8)
.\" This file is in the public domain, so clarified as of
.\" 2009-05-17 by Arthur David Olson.
285 changes: 168 additions & 117 deletions zic.c

Large diffs are not rendered by default.

26 changes: 13 additions & 13 deletions zone.tab
@@ -114,8 +114,7 @@ CA +4606-06447 America/Moncton Atlantic - New Brunswick
CA +5320-06025 America/Goose_Bay Atlantic - Labrador (most areas) CA +5320-06025 America/Goose_Bay Atlantic - Labrador (most areas)
CA +5125-05707 America/Blanc-Sablon AST - QC (Lower North Shore) CA +5125-05707 America/Blanc-Sablon AST - QC (Lower North Shore)
CA +4339-07923 America/Toronto Eastern - ON, QC (most areas) CA +4339-07923 America/Toronto Eastern - ON, QC (most areas)
CA +6344-06828 America/Iqaluit Eastern - NU (most east areas) CA +6344-06828 America/Iqaluit Eastern - NU (most areas)
CA +6608-06544 America/Pangnirtung Eastern - NU (Pangnirtung)
CA +484531-0913718 America/Atikokan EST - ON (Atikokan); NU (Coral H) CA +484531-0913718 America/Atikokan EST - ON (Atikokan); NU (Coral H)
CA +4953-09709 America/Winnipeg Central - ON (west); Manitoba CA +4953-09709 America/Winnipeg Central - ON (west); Manitoba
CA +744144-0944945 America/Resolute Central - NU (Resolute) CA +744144-0944945 America/Resolute Central - NU (Resolute)
@@ -277,17 +276,18 @@ MT +3554+01431 Europe/Malta
MU -2010+05730 Indian/Mauritius MU -2010+05730 Indian/Mauritius
MV +0410+07330 Indian/Maldives MV +0410+07330 Indian/Maldives
MW -1547+03500 Africa/Blantyre MW -1547+03500 Africa/Blantyre
MX +1924-09909 America/Mexico_City Central Time MX +1924-09909 America/Mexico_City Central Mexico
MX +2105-08646 America/Cancun Eastern Standard Time - Quintana Roo MX +2105-08646 America/Cancun Quintana Roo
MX +2058-08937 America/Merida Central Time - Campeche, Yucatan MX +2058-08937 America/Merida Campeche, Yucatan
MX +2540-10019 America/Monterrey Central Time - Durango; Coahuila, Nuevo Leon, Tamaulipas (most areas) MX +2540-10019 America/Monterrey Durango; Coahuila, Nuevo Leon, Tamaulipas (most areas)
MX +2550-09730 America/Matamoros Central Time US - Coahuila, Nuevo Leon, Tamaulipas (US border) MX +2550-09730 America/Matamoros Coahuila, Nuevo Leon, Tamaulipas (US border)
MX +2313-10625 America/Mazatlan Mountain Time - Baja California Sur, Nayarit, Sinaloa MX +2838-10605 America/Chihuahua Chihuahua (most areas)
MX +2838-10605 America/Chihuahua Mountain Time - Chihuahua (most areas) MX +3144-10629 America/Ciudad_Juarez Chihuahua (US border - west)
MX +2934-10425 America/Ojinaga Mountain Time US - Chihuahua (US border) MX +2934-10425 America/Ojinaga Chihuahua (US border - east)
MX +2904-11058 America/Hermosillo Mountain Standard Time - Sonora MX +2313-10625 America/Mazatlan Baja California Sur, Nayarit (most areas), Sinaloa
MX +3232-11701 America/Tijuana Pacific Time US - Baja California MX +2048-10515 America/Bahia_Banderas Bahia de Banderas
MX +2048-10515 America/Bahia_Banderas Central Time - Bahia de Banderas MX +2904-11058 America/Hermosillo Sonora
MX +3232-11701 America/Tijuana Baja California
MY +0310+10142 Asia/Kuala_Lumpur Malaysia (peninsula) MY +0310+10142 Asia/Kuala_Lumpur Malaysia (peninsula)
MY +0133+11020 Asia/Kuching Sabah, Sarawak MY +0133+11020 Asia/Kuching Sabah, Sarawak
MZ -2558+03235 Africa/Maputo MZ -2558+03235 Africa/Maputo
26 changes: 13 additions & 13 deletions zone1970.tab
@@ -102,8 +102,7 @@ CA +4612-05957 America/Glace_Bay Atlantic - NS (Cape Breton)
CA +4606-06447 America/Moncton Atlantic - New Brunswick CA +4606-06447 America/Moncton Atlantic - New Brunswick
CA +5320-06025 America/Goose_Bay Atlantic - Labrador (most areas) CA +5320-06025 America/Goose_Bay Atlantic - Labrador (most areas)
CA,BS +4339-07923 America/Toronto Eastern - ON, QC (most areas), Bahamas CA,BS +4339-07923 America/Toronto Eastern - ON, QC (most areas), Bahamas
CA +6344-06828 America/Iqaluit Eastern - NU (most east areas) CA +6344-06828 America/Iqaluit Eastern - NU (most areas)
CA +6608-06544 America/Pangnirtung Eastern - NU (Pangnirtung)
CA +4953-09709 America/Winnipeg Central - ON (west); Manitoba CA +4953-09709 America/Winnipeg Central - ON (west); Manitoba
CA +744144-0944945 America/Resolute Central - NU (Resolute) CA +744144-0944945 America/Resolute Central - NU (Resolute)
CA +624900-0920459 America/Rankin_Inlet Central - NU (central) CA +624900-0920459 America/Rankin_Inlet Central - NU (central)
@@ -214,17 +213,18 @@ MQ +1436-06105 America/Martinique
MT +3554+01431 Europe/Malta MT +3554+01431 Europe/Malta
MU -2010+05730 Indian/Mauritius MU -2010+05730 Indian/Mauritius
MV,TF +0410+07330 Indian/Maldives Maldives, Kerguelen, St Paul I, Amsterdam I MV,TF +0410+07330 Indian/Maldives Maldives, Kerguelen, St Paul I, Amsterdam I
MX +1924-09909 America/Mexico_City Central Time MX +1924-09909 America/Mexico_City Central Mexico
MX +2105-08646 America/Cancun Eastern Standard Time - Quintana Roo MX +2105-08646 America/Cancun Quintana Roo
MX +2058-08937 America/Merida Central Time - Campeche, Yucatán MX +2058-08937 America/Merida Campeche, Yucatán
MX +2540-10019 America/Monterrey Central Time - Durango; Coahuila, Nuevo León, Tamaulipas (most areas) MX +2540-10019 America/Monterrey Durango; Coahuila, Nuevo León, Tamaulipas (most areas)
MX +2550-09730 America/Matamoros Central Time US - Coahuila, Nuevo León, Tamaulipas (US border) MX +2550-09730 America/Matamoros Coahuila, Nuevo León, Tamaulipas (US border)
MX +2313-10625 America/Mazatlan Mountain Time - Baja California Sur, Nayarit, Sinaloa MX +2838-10605 America/Chihuahua Chihuahua (most areas)
MX +2838-10605 America/Chihuahua Mountain Time - Chihuahua (most areas) MX +3144-10629 America/Ciudad_Juarez Chihuahua (US border - west)
MX +2934-10425 America/Ojinaga Mountain Time US - Chihuahua (US border) MX +2934-10425 America/Ojinaga Chihuahua (US border - east)
MX +2904-11058 America/Hermosillo Mountain Standard Time - Sonora MX +2313-10625 America/Mazatlan Baja California Sur, Nayarit (most areas), Sinaloa
MX +3232-11701 America/Tijuana Pacific Time US - Baja California MX +2048-10515 America/Bahia_Banderas Bahía de Banderas
MX +2048-10515 America/Bahia_Banderas Central Time - Bahía de Banderas MX +2904-11058 America/Hermosillo Sonora
MX +3232-11701 America/Tijuana Baja California
MY,BN +0133+11020 Asia/Kuching Sabah, Sarawak, Brunei MY,BN +0133+11020 Asia/Kuching Sabah, Sarawak, Brunei
MZ,BI,BW,CD,MW,RW,ZM,ZW -2558+03235 Africa/Maputo Central Africa Time MZ,BI,BW,CD,MW,RW,ZM,ZW -2558+03235 Africa/Maputo Central Africa Time
NA -2234+01706 Africa/Windhoek NA -2234+01706 Africa/Windhoek